From 39f9ee5574c395bf6c2fa6c395f957e8c80ac80c Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sat, 3 Jun 2023 11:23:37 -0400 Subject: [PATCH 01/18] Fix project var. APP_NAME --- app/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 206ad15..4d7ba46 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -38,5 +38,5 @@ ob_add_cpp_vars(${APP_TARGET_NAME} VARS VERSION_STR "\"${PROJECT_VERSION}\"" SHORT_NAME "\"${PROJECT_NAME}\"" - APP_NAME "\"${APP_NAME}\"" + APP_NAME "\"${PROJECT_NAME_FORMAL}\"" ) From d841f5f7e67cde1970690805c7f4d5513a08af02 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Tue, 6 Jun 2023 15:42:11 -0400 Subject: [PATCH 02/18] Fix doc mainpage typo --- doc/cmake/file_templates/mainpage.md.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/cmake/file_templates/mainpage.md.in b/doc/cmake/file_templates/mainpage.md.in index 77dfb63..236f0f3 100644 --- a/doc/cmake/file_templates/mainpage.md.in +++ b/doc/cmake/file_templates/mainpage.md.in @@ -284,4 +284,4 @@ target_link_libraries(SomeExe ) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This allows for more flexibility in downstream projects as they can more easily alter the configuration of libsquish on-the-fly as needed. \ No newline at end of file +This allows for more flexibility in downstream projects as they can more easily alter the configuration of STAR++ on-the-fly as needed. \ No newline at end of file From 631ddd5373afb4e69bc3f4beb5f815e8d2b4b825 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Thu, 8 Jun 2023 00:46:36 -0400 Subject: [PATCH 03/18] Fix README.md typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ccb67d8..a4791cd 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Using no calculator options will result in the application following the recomme ## Pre-built Releases/Artifacts -Releases and some workflows currently provide builds of libsquish in various combinations of platforms and compilers. View the repository [Actions](https://github.com/oblivioncth/STARpp/actions) or [Releases](https://github.com/oblivioncth/STARpp/releases) to see examples +Releases and some workflows currently provide builds of STARpp in various combinations of platforms and compilers. View the repository [Actions](https://github.com/oblivioncth/STARpp/actions) or [Releases](https://github.com/oblivioncth/STARpp/releases) to see examples ### Details The source for this project is managed by a sensible CMake configuration that allows for straightforward compilation and consumption of its target(s), either as a sub-project or as an imported package. All required dependencies except for Qt6 and Doxygen are automatically acquired via CMake's FetchContent mechanism. From 1574214d4a0bfa2af4d99e0664a44e124caccfe1 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Thu, 2 Nov 2023 02:13:19 -0400 Subject: [PATCH 04/18] Change license to MPL --- LICENSE | 1034 ++++++++++++++++++++----------------------------------- 1 file changed, 373 insertions(+), 661 deletions(-) diff --git a/LICENSE b/LICENSE index 0ad25db..f4bbcd2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,661 +1,373 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - 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 -them 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. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If 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 convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state 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 program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. \ No newline at end of file From 4196fc5c43f18c37810b2681c94b99bf6ff10cf8 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 3 Dec 2023 17:00:29 -0500 Subject: [PATCH 05/18] Conform to dependency updates --- CMakeLists.txt | 6 +- app/CMakeLists.txt | 1 - app/src/core.cpp | 69 ++++++++++----- app/src/core.h | 68 +++++++++++--- app/src/errorcode.h | 14 --- app/src/main.cpp | 33 +++++-- lib/include/star/expectedelectionresult.h | 1 - lib/src/expectedelectionresult.cpp | 10 +-- lib/src/reference.cpp | 17 ++-- lib/src/reference/ballotbox_p.cpp | 54 ++++++++---- lib/src/reference/ballotbox_p.h | 93 +++++++++++++++---- lib/src/reference/calculatoroptions_p.cpp | 37 ++++++-- lib/src/reference/calculatoroptions_p.h | 68 ++++++++++++-- lib/src/reference/categoryconfig_p.cpp | 54 ++++++++---- lib/src/reference/categoryconfig_p.h | 101 ++++++++++++++++----- lib/src/reference/resultset_p.cpp | 103 ++++++++-------------- lib/src/reference/resultset_p.h | 21 +---- 17 files changed, 510 insertions(+), 240 deletions(-) delete mode 100644 app/src/errorcode.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a4811df..733ffd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ project(STARpp # Get helper scripts include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchOBCMake.cmake) -fetch_ob_cmake("v0.3") +fetch_ob_cmake("v0.3.4") # Initialize project according to standard rules include(OB/Project) @@ -65,14 +65,14 @@ set(STARPP_QX_COMPONENTS include(OB/FetchQx) ob_fetch_qx( - REF "v0.5" + REF "v0.5.6" COMPONENTS ${STARPP_QX_COMPONENTS} ) # Fetch Neargye's Magic Enum include(OB/FetchMagicEnum) -ob_fetch_magicenum("v0.8.0") +ob_fetch_magicenum("v0.9.5") # Process Targets set(LIB_TARGET_NAME ${PROJECT_NAMESPACE_LC}_base) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 4d7ba46..e846069 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -16,7 +16,6 @@ ob_add_standard_executable(${APP_TARGET_NAME} SOURCE core.h core.cpp - errorcode.h referenceelectionconfig.h resultspresenter.h resultspresenter.cpp diff --git a/app/src/core.cpp b/app/src/core.cpp index ec170c1..6b6c2e5 100644 --- a/app/src/core.cpp +++ b/app/src/core.cpp @@ -11,6 +11,30 @@ // Macros #define ENUM_NAME(eenum) QString(magic_enum::enum_name(eenum).data()) +//=============================================================================================================== +// CoreError +//=============================================================================================================== + +//-Constructor------------------------------------------------------------- +//Private: +CoreError::CoreError(Type t, const QString& s, Qx::Severity sv) : + mType(t), + mSpecific(s), + mSeverity(sv) +{} + +//-Instance Functions------------------------------------------------------------- +//Public: +bool CoreError::isValid() const { return mType != NoError; } +QString CoreError::specific() const { return mSpecific; } +CoreError::Type CoreError::type() const { return mType; } + +//Private: +Qx::Severity CoreError::deriveSeverity() const { return mSeverity; } +quint32 CoreError::deriveValue() const { return mType; } +QString CoreError::derivePrimary() const { return ERR_STRINGS.value(mType); } +QString CoreError::deriveSecondary() const { return mSpecific; } + //=============================================================================================================== // CORE //=============================================================================================================== @@ -31,13 +55,13 @@ Core::Core(QCoreApplication* app) : //-Instance Functions------------------------------------------------------------- //Private: -void Core::handleLogError(Qx::IoOpReport error) +void Core::handleLogError(const Qx::IoOpReport& error) { // Note error mLogErrorOccurred = true; // Post error - static Qx::GenericError errorMsg(Qx::GenericError::Warning, ERR_LOG_ERROR, error.outcomeInfo()); + static CoreError errorMsg(CoreError::LogError, error.outcomeInfo(), Qx::Warning); Qx::cout << errorMsg; } @@ -75,18 +99,18 @@ void Core::showVersion() postMessage(CL_VERSION_MESSAGE); } -void Core::logElectionData(const ReferenceElectionConfig data) +void Core::logElectionData(const ReferenceElectionConfig& data) { logEvent(NAME, LOG_EVENT_ELECTION_DATA_PROVIDED.arg(data.bbPath, data.ccPath)); } //Public: -ErrorCode Core::initialize() +Qx::Error Core::initialize() { // Open log Qx::IoOpReport logOpen = mLogger.openLog(); if(logOpen.isFailure()) - postError(NAME, Qx::GenericError(Qx::GenericError::Warning, logOpen.outcome(), logOpen.outcomeInfo())); + postError(NAME, Qx::Error(logOpen).setSeverity(Qx::Warning)); // Log initialization step logEvent(NAME, LOG_EVENT_INIT); @@ -100,9 +124,10 @@ ErrorCode Core::initialize() // Parse if(!clParser.parse(mArguments)) { - postError(NAME, Qx::GenericError(Qx::GenericError::Error, LOG_ERR_INVALID_ARGS, clParser.errorText())); + CoreError err(CoreError::InvalidArgs, clParser.errorText()); + postError(NAME, err); showHelp(); - return ErrorCode::INVALID_ARGS; + return err; } // Handle arguments @@ -141,8 +166,9 @@ ErrorCode Core::initialize() } else { - postError(NAME, Qx::GenericError(Qx::GenericError::Error, LOG_ERR_INVALID_CALC_OPTION, optStr)); - return ErrorCode::INVALID_CALC_OPT; + CoreError err(CoreError::InvalidCalcOption, optStr); + postError(NAME, err); + return err; } } @@ -160,12 +186,13 @@ ErrorCode Core::initialize() } else { - logError(NAME, Qx::GenericError(Qx::GenericError::Error, LOG_ERR_INVALID_ARGS, ERR_MISSING_REF_PATHS)); - return ErrorCode::INVALID_ARGS; + CoreError err(CoreError::InvalidArgs, ERR_MISSING_REF_PATHS); + logError(NAME, err); + return err; } // Return success - return ErrorCode::NO_ERR; + return CoreError(); } bool Core::hasActionableArguments() const { return mRefElectionCfg.has_value(); } @@ -181,7 +208,7 @@ bool Core::isMinimalPresentation() const { return mMinimal; } //-Signals & Slots------------------------------------------------------------------------------------------------------------ //Public slots: -void Core::logError(QString src, Qx::GenericError error) +void Core::logError(const QString& src, const Qx::Error& error) { if(!mLogErrorOccurred) { @@ -191,7 +218,7 @@ void Core::logError(QString src, Qx::GenericError error) } } -void Core::logEvent(QString src, QString event) +void Core::logEvent(const QString& src, const QString& event) { if(!mLogErrorOccurred) { @@ -201,27 +228,29 @@ void Core::logEvent(QString src, QString event) } } -void Core::logCalculatorDetail(QString detail) { logEvent("Calculator", detail); } +void Core::logCalculatorDetail(const QString& detail) { logEvent("Calculator", detail); } -ErrorCode Core::logFinish(ErrorCode exitCode) +ErrorCode Core::logFinish(const Qx::Error& errorState) { + ErrorCode code = errorState.typeCode(); + if(!mLogErrorOccurred) { - Qx::IoOpReport lr = mLogger.finish(exitCode); + Qx::IoOpReport lr = mLogger.finish(code); if(lr.isFailure()) handleLogError(lr); } - return exitCode; + return code; } -void Core::postError(QString src, Qx::GenericError error) +void Core::postError(const QString& src, const Qx::Error& error) { Qx::cout << error << Qt::endl; logError(src, error); } -void Core::postMessage(QString msg) +void Core::postMessage(const QString& msg) { Qx::cout << msg << Qt::endl; } diff --git a/app/src/core.h b/app/src/core.h index c262ad2..bba6953 100644 --- a/app/src/core.h +++ b/app/src/core.h @@ -14,11 +14,57 @@ #include // Project Includes -#include "errorcode.h" #include "star/calculator.h" #include "referenceelectionconfig.h" #include "project_vars.h" +using ErrorCode = quint32; + +class QX_ERROR_TYPE(CoreError, "CoreError", 1200) +{ + friend class Core; +//-Class Enums------------------------------------------------------------- +public: + enum Type + { + NoError, + LogError, + InvalidArgs, + InvalidCalcOption + }; + +//-Class Variables------------------------------------------------------------- +private: + static inline const QHash ERR_STRINGS{ + {NoError, u""_s}, + {LogError, u"Error writing to log"_s}, + {InvalidArgs, u"Invalid arguments provided."_s}, + {InvalidCalcOption, u"Invalid calculator option provided."_s} + }; + +//-Instance Variables------------------------------------------------------------- +private: + Type mType; + QString mSpecific; + Qx::Severity mSeverity; + +//-Constructor------------------------------------------------------------- +private: + CoreError(Type t = NoError, const QString& s = {}, Qx::Severity sv = Qx::Critical); + +//-Instance Functions------------------------------------------------------------- +public: + bool isValid() const; + Type type() const; + QString specific() const; + +private: + Qx::Severity deriveSeverity() const override; + quint32 deriveValue() const override; + QString derivePrimary() const override; + QString deriveSecondary() const override; +}; + class Core : public QObject { Q_OBJECT; @@ -32,7 +78,6 @@ class Core : public QObject static inline const QString LOG_FILE_EXT = QStringLiteral("log"); // Logging - Errors - static inline const QString LOG_ERR_INVALID_ARGS = QStringLiteral("Invalid arguments provided."); static inline const QString LOG_ERR_INVALID_CALC_OPTION = QStringLiteral("Invalid calculator option provided."); // Logging - Messages @@ -74,6 +119,7 @@ class Core : public QObject /* NOTE: This will cause a compilation error when changing Star::Calculator::Options in order to prompt the developer * to ensure any new options have been described above and then manually check them off here */ +# static_assert(magic_enum::enum_values() == std::array{ Star::Calculator::NoOptions, Star::Calculator::AllowTrueTies, @@ -134,14 +180,14 @@ class Core : public QObject //-Instance Functions------------------------------------------------------------------------------------------------------ private: - void handleLogError(Qx::IoOpReport error); + void handleLogError(const Qx::IoOpReport& error); void showHelp(); void showVersion(); - void logElectionData(const ReferenceElectionConfig data); + void logElectionData(const ReferenceElectionConfig& data); public: - ErrorCode initialize(); + Qx::Error initialize(); bool hasActionableArguments() const; ReferenceElectionConfig referenceElectionConfig() const; Star::Calculator::Options calculatorOptions() const; @@ -149,13 +195,13 @@ class Core : public QObject //-Signals & Slots------------------------------------------------------------------------------------------------------------ public slots: - void logError(QString src, Qx::GenericError error); - void logEvent(QString src, QString event); - void logCalculatorDetail(QString detail); - ErrorCode logFinish(ErrorCode exitCode); + void logError(const QString& src, const Qx::Error& error); + void logEvent(const QString& src, const QString& event); + void logCalculatorDetail(const QString& detail); + ErrorCode logFinish(const Qx::Error& errorState); - void postError(QString src, Qx::GenericError error); - void postMessage(QString msg); + void postError(const QString& src, const Qx::Error& error); + void postMessage(const QString& msg); }; #endif // CORE_H diff --git a/app/src/errorcode.h b/app/src/errorcode.h deleted file mode 100644 index 3f2d422..0000000 --- a/app/src/errorcode.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef ERRORCODE_H -#define ERRORCODE_H - -enum ErrorCode{ - // Common - NO_ERR = 0, - INVALID_ARGS = 1, - INVALID_CALC_OPT = 2, - - // Reference - INVALID_REF_ELECTION = 100 -}; - -#endif // ERRORCODE_H diff --git a/app/src/main.cpp b/app/src/main.cpp index 412c297..41f3794 100644 --- a/app/src/main.cpp +++ b/app/src/main.cpp @@ -3,6 +3,7 @@ // Qx Includes #include +#include // Base Includes #include "star/election.h" @@ -27,6 +28,26 @@ const QString MSG_CALCULING_ELECTION_RESULTS = QStringLiteral("Calculating elect // Meta const QString NAME = QStringLiteral("Main"); +// Ref Error adapter +class QX_ERROR_TYPE(ReferenceErrorAdapter, "Star::ReferenceError", 1201) +{ +private: + const Star::ReferenceError& mErrorRef; + +public: + ReferenceErrorAdapter(const Star::ReferenceError& e) : + mErrorRef(e) + {} + ReferenceErrorAdapter(ReferenceErrorAdapter&&) = delete; + ReferenceErrorAdapter(const ReferenceErrorAdapter&) = delete; + +private: + quint32 deriveValue() const override { return static_cast(mErrorRef.type); } + QString derivePrimary() const override { return mErrorRef.error; } + QString deriveSecondary() const override { return mErrorRef.errorDetails; } +}; +QX_DECLARE_ERROR_ADAPTATION(Star::ReferenceError, ReferenceErrorAdapter); + int main(int argc, char *argv[]) { // Setup application @@ -40,15 +61,15 @@ int main(int argc, char *argv[]) // Create core and initialize it Core core(&app); - ErrorCode initError = core.initialize(); - if(initError) + Qx::Error initError = core.initialize(); + if(initError.isValid()) return core.logFinish(initError); // Check if election was provided if(!core.hasActionableArguments()) { core.logEvent(NAME, LOG_EVENT_NO_ELECTION); - return core.logFinish(ErrorCode::NO_ERR); + return core.logFinish(Qx::Error()); } // Load reference election @@ -59,8 +80,8 @@ int main(int argc, char *argv[]) Star::ReferenceError refError = Star::electionsFromReferenceInput(elections, rec.ccPath, rec.bbPath); if(refError.isValid()) { - core.postError(NAME, Qx::GenericError(Qx::GenericError::Critical, refError.error, refError.errorDetails)); - return core.logFinish(ErrorCode::INVALID_REF_ELECTION); + core.postError(NAME, refError); + return core.logFinish(refError); } core.logEvent(NAME, LOG_EVENT_ELECTION_COUNT.arg(elections.size())); @@ -86,5 +107,5 @@ int main(int argc, char *argv[]) ResultPresenter presenter(&results, core.isMinimalPresentation()); presenter.present(); - return core.logFinish(ErrorCode::NO_ERR); + return core.logFinish(Qx::Error()); } diff --git a/lib/include/star/expectedelectionresult.h b/lib/include/star/expectedelectionresult.h index 1c9b452..b0e686b 100644 --- a/lib/include/star/expectedelectionresult.h +++ b/lib/include/star/expectedelectionresult.h @@ -36,7 +36,6 @@ class STAR_BASE_EXPORT ExpectedElectionResult QList seats() const; bool operator==(const ElectionResult& result) const; - bool operator!=(const ElectionResult& result) const; }; class STAR_BASE_EXPORT ExpectedElectionResult::Builder diff --git a/lib/src/expectedelectionresult.cpp b/lib/src/expectedelectionresult.cpp index e25eb0a..696dbfd 100644 --- a/lib/src/expectedelectionresult.cpp +++ b/lib/src/expectedelectionresult.cpp @@ -75,21 +75,13 @@ QList ExpectedElectionResult::seats() const { return mSeats; } * Returns @c true if this expected election result is the same as the election result * @a result; otherwise, returns @c false. * - * @sa operator!=() and sameOutcomeAs(). + * @sa sameOutcomeAs(). */ bool ExpectedElectionResult::operator==(const ElectionResult& result) const { return mSeats == result.seats(); } -/*! - * Returns @c true if this expected election result is not the same as the election result - * @a result; otherwise, returns @c false. - * - * @sa operator==() and sameOutcomeAs(). - */ -bool ExpectedElectionResult::operator!=(const ElectionResult& result) const { return !(*this == result); } - //=============================================================================================================== // ExpectedElectionResult::Builder //=============================================================================================================== diff --git a/lib/src/reference.cpp b/lib/src/reference.cpp index bb34a0a..1372123 100644 --- a/lib/src/reference.cpp +++ b/lib/src/reference.cpp @@ -5,6 +5,9 @@ #include "reference/ballotbox_p.h" #include "reference/resultset_p.h" +// Qx Includes +#include + /*! * @file reference.h * @@ -186,12 +189,12 @@ namespace return views; } - ReferenceError qxGenErrToRefError(ReferenceErrorType type, const Qx::GenericError& error) + ReferenceError qxErrToRefError(ReferenceErrorType type, const Qx::Error& error) { if(!error.isValid()) return ReferenceError(); - return ReferenceError{ .type = type, .error = error.primaryInfo(), .errorDetails = error.secondaryInfo() }; + return ReferenceError{ .type = type, .error = error.primary(), .errorDetails = error.secondary() }; } } @@ -210,19 +213,19 @@ ReferenceError electionsFromReferenceInput(QList& returnBuffer, returnBuffer.clear(); // Status tracker - Qx::GenericError errorStatus; + Qx::Error errorStatus; // Read category config RefCategoryConfig cc; RefCategoryConfig::Reader ccReader(&cc, categoryConfigPath); if((errorStatus = ccReader.readInto()).isValid()) - return qxGenErrToRefError(ReferenceErrorType::CategoryConfig, errorStatus); + return qxErrToRefError(ReferenceErrorType::CategoryConfig, errorStatus); // Read ballot box RefBallotBox bb; RefBallotBox::Reader bbReader(&bb, ballotBoxPath, &cc); if((errorStatus = bbReader.readInto()).isValid()) - return qxGenErrToRefError(ReferenceErrorType::BallotBox, errorStatus); + return qxErrToRefError(ReferenceErrorType::BallotBox, errorStatus); // Create elections from standard ballot box @@ -245,7 +248,7 @@ ReferenceError expectedResultsFromReferenceInput(QList& // Read file ResultSetReader rsReader(&returnBuffer, resultSetPath); - return qxGenErrToRefError(ReferenceErrorType::ExpectedResult, rsReader.readInto()); + return qxErrToRefError(ReferenceErrorType::ExpectedResult, rsReader.readInto()); } /*! @@ -262,7 +265,7 @@ ReferenceError calculatorOptionsFromReferenceInput(Star::Calculator::Options& re // Read file CalcOptionsReader opReader(&returnBuffer, calcOptionsPath); - return qxGenErrToRefError(ReferenceErrorType::CalcOptions, opReader.readInto()); + return qxErrToRefError(ReferenceErrorType::CalcOptions, opReader.readInto()); } } diff --git a/lib/src/reference/ballotbox_p.cpp b/lib/src/reference/ballotbox_p.cpp index 7f94907..0b15dab 100644 --- a/lib/src/reference/ballotbox_p.cpp +++ b/lib/src/reference/ballotbox_p.cpp @@ -11,6 +11,28 @@ namespace Star { /*! @cond */ +//=============================================================================================================== +// RefBallotBoxError +//=============================================================================================================== + +//-Constructor-------------------------------------------------------------------- +RefBallotBoxError::RefBallotBoxError(Type t) : + mType(t), + mString(ERR_STRINGS.value(t)) +{} + +//-Instance Functions------------------------------------------------------------- +//Public: +bool RefBallotBoxError::isValid() const { return mType != NoError; } +RefBallotBoxError::Type RefBallotBoxError::type() const { return mType; } +QString RefBallotBoxError::string() const { return mString; } + +//Private: +Qx::Severity RefBallotBoxError::deriveSeverity() const { return Qx::Critical; } +quint32 RefBallotBoxError::deriveValue() const { return mType; } +QString RefBallotBoxError::derivePrimary() const { return MAIN_ERR_MSG; } +QString RefBallotBoxError::deriveSecondary() const { return mString; } + //=============================================================================================================== // RefBallotBox //=============================================================================================================== @@ -39,7 +61,7 @@ RefBallotBox::Reader::Reader(RefBallotBox* targetBox, const QString& filePath, c //-Instance Functions------------------------------------------------------------------------------------------------- //Private: -Qx::GenericError RefBallotBox::Reader::parseCategories(const QList& headingsRow) +RefBallotBoxError RefBallotBox::Reader::parseCategories(const QList& headingsRow) { // Fill out categories qsizetype cIdx = STATIC_FIELD_COUNT; // Skip known headings @@ -54,10 +76,10 @@ Qx::GenericError RefBallotBox::Reader::parseCategories(const QList& he { QString candidateField = headingsRow[cIdx].toString().trimmed(); if(candidateField.isEmpty()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_BLANK_VALUE.arg(0).arg(cIdx)); + return RefBallotBoxError(RefBallotBoxError::BlankValue, 0, cIdx); if(candidates.contains(candidateField)) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_DUPLICATE_CANDIDATE); + return RefBallotBoxError(RefBallotBoxError::DuplicateCandidate); candidates += candidateField; } @@ -66,10 +88,10 @@ Qx::GenericError RefBallotBox::Reader::parseCategories(const QList& he mTargetBox->mCategories.append(category); } - return Qx::GenericError(); + return RefBallotBoxError(); } -Qx::GenericError RefBallotBox::Reader::parseBallot(const QList& ballotRow, qsizetype ballotNum) +RefBallotBoxError RefBallotBox::Reader::parseBallot(const QList& ballotRow, qsizetype ballotNum) { // Ignore lines with all empty fields bool allEmpty = true; @@ -83,7 +105,7 @@ Qx::GenericError RefBallotBox::Reader::parseBallot(const QList& ballot } if(allEmpty) - return Qx::GenericError(); + return RefBallotBoxError(); // Read submission date QDate submitted = QDate::fromString(ballotRow[SUBMISSION_DATE_INDEX].toString(), "d-MMM-yy").addYears(100); @@ -94,7 +116,7 @@ Qx::GenericError RefBallotBox::Reader::parseBallot(const QList& ballot // Read voter name QString voterName = ballotRow[MEMBER_NAME_INDEX].toString(); if(voterName.isEmpty()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_BLANK_VALUE.arg(ballotNum).arg(MEMBER_NAME_INDEX)); + return RefBallotBoxError(RefBallotBoxError::BlankValue, ballotNum, MEMBER_NAME_INDEX); // Create ballot with existing info RefBallot ballot{.voter = voterName, .submissionDate = submitted, .votes = {}}; @@ -122,7 +144,7 @@ Qx::GenericError RefBallotBox::Reader::parseBallot(const QList& ballot int vote = voteField.toUInt(&validValue); // Stored as int, but should be a uint if(!validValue || vote > 5) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_INVALID_VOTE.arg(ballotNum).arg(cIdx)); + return RefBallotBoxError(RefBallotBoxError::InvalidVote, ballotNum, cIdx); categoryVotes.append(vote); } @@ -133,38 +155,38 @@ Qx::GenericError RefBallotBox::Reader::parseBallot(const QList& ballot // Add ballot to box mTargetBox->mBallots.append(ballot); - return Qx::GenericError(); + return RefBallotBoxError(); } //Public: -Qx::GenericError RefBallotBox::Reader::readInto() +RefBallotBoxError RefBallotBox::Reader::readInto() { // Error tracking - Qx::GenericError errorStatus; + RefBallotBoxError errorStatus; // Quickly check if file is empty if(Qx::fileIsEmpty(mCsvFile)) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_EMPTY); + return RefBallotBoxError(RefBallotBoxError::Empty); // Read whole CSV into memory as raw data QByteArray csv; Qx::IoOpReport readReport = Qx::readBytesFromFile(csv, mCsvFile); if(readReport.isFailure()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(readReport.outcomeInfo()); + return RefBallotBoxError(RefBallotBoxError::IoError, readReport.outcomeInfo()); // Parse into DsvTable Qx::DsvParseError dsvError; Qx::DsvTable csvTable = Qx::DsvTable::fromDsv(csv, ',', '"', &dsvError); if(dsvError.error() != Qx::DsvParseError::NoError) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(dsvError.errorString()); + return RefBallotBoxError(RefBallotBoxError::IoError, dsvError.errorString()); // Ensure the minimum amount of rows are present if(csvTable.rowCount() < 3) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_INVALID_ROW_COUNT); + return RefBallotBoxError(RefBallotBoxError::InvalidRowCount); // Ensure the column count is correct if(csvTable.columnCount() != mExpectedFieldCount) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_INVALID_COLUMN_COUNT.arg(csvTable.columnCount()).arg(mExpectedFieldCount)); + return RefBallotBoxError(RefBallotBoxError::InvalidColumnCount, csvTable.columnCount(), mExpectedFieldCount); // Separate headings from ballot rows QList headingRow = csvTable.takeFirstRow(); diff --git a/lib/src/reference/ballotbox_p.h b/lib/src/reference/ballotbox_p.h index b826717..e4375c3 100644 --- a/lib/src/reference/ballotbox_p.h +++ b/lib/src/reference/ballotbox_p.h @@ -8,7 +8,7 @@ #include // Qx Includes -#include +#include namespace Star { @@ -30,6 +30,78 @@ struct RefBallot QList> votes; }; +class QX_ERROR_TYPE(RefBallotBoxError, "Star::RefBallotBoxError", 1150) +{ + friend class RefBallotBox; +//-Class Enums------------------------------------------------------------- +public: + enum Type + { + NoError, + InvalidRowCount, + InvalidColumnCount, + InvalidDate, + Empty, + BlankValue, + InvalidVote, + DuplicateCandidate, + IoError + }; + +//-Class Variables------------------------------------------------------------- +private: + static inline const QString MAIN_ERR_MSG = u"Error reading the ballot box."_s; + static inline const QHash ERR_STRINGS{ + {NoError, u""_s}, + {InvalidRowCount, u"The ballot box has less than the minimum required row count (headings + 2 voters)."_s}, + {InvalidColumnCount, u"The ballot box has a different number of columns than specified by the category configuration (%1 vs %2)."_s}, + {InvalidDate, u"The format of a submission date was invalid."_s}, + {Empty, u"The provided file contains no ballots."_s}, + {BlankValue, u"A field expected to have a value was blank (r: %1, c: %2)."_s}, + {InvalidVote, u"A vote value was not a valid unsigned integer between 0 and 5 (r: %1, c: %2)."_s}, + {DuplicateCandidate, u"The ballot box contained duplicate candidates within the same category."_s}, + {IoError, u"IO Error: %1"_s} + }; + +//-Instance Variables------------------------------------------------------------- +private: + Type mType; + QString mString; + +//-Constructor------------------------------------------------------------- +private: + RefBallotBoxError(Type t = NoError); + + template + requires (std::same_as && ...) + RefBallotBoxError(Type t, Strings... args) : + RefBallotBoxError(t) + { + mString = mString.arg(args...); + } + + template + requires (std::integral && ...) + RefBallotBoxError(Type t, Ints... args) : + RefBallotBoxError(t) + { + auto sub = [this](auto integer) { mString = mString.arg(integer); }; + (sub(args), ...); + } + +//-Instance Functions------------------------------------------------------------- +public: + bool isValid() const; + Type type() const; + QString string() const; + +private: + Qx::Severity deriveSeverity() const override; + quint32 deriveValue() const override; + QString derivePrimary() const override; + QString deriveSecondary() const override; +}; + class RefBallotBox { //-Inner Classes---------------------------------------------------------------------------------------------------- @@ -55,19 +127,6 @@ class RefBallotBox::Reader { //-Class Variables-------------------------------------------------------------------------------------------------- private: - // Error - static inline const QString MAIN_ERR_MSG = QStringLiteral("Error reading the ballot box."); - - static inline const QString ERR_INVALID_ROW_COUNT = QStringLiteral("The ballot box has less than the minimum required row count (headings + 2 voters)."); - static inline const QString ERR_INVALID_COLUMN_COUNT = QStringLiteral("The ballot box has a different number of columns than specified by the category configuration (%1 vs %2)."); - static inline const QString ERR_INVALID_DATE = QStringLiteral("The format of a submission date was invalid."); - static inline const QString ERR_EMPTY = QStringLiteral("The provided file contains no ballots."); - static inline const QString ERR_BLANK_VALUE = QStringLiteral("A field expected to have a value was blank (r: %1, c: %2)."); - static inline const QString ERR_INVALID_VOTE = QStringLiteral("A vote value was not a valid unsigned integer between 0 and 5 (r: %1, c: %2)."); - static inline const QString ERR_DUPLICATE_CANDIDATE = QStringLiteral("The ballot box contained duplicate candidates within the same category."); - - static inline const Qx::GenericError ERROR_TEMPLATE = Qx::GenericError(Qx::GenericError::Critical, MAIN_ERR_MSG); - // Fields static const int STATIC_FIELD_COUNT = 2; static const int SUBMISSION_DATE_INDEX = 0; @@ -86,11 +145,11 @@ class RefBallotBox::Reader //-Instance Functions------------------------------------------------------------------------------------------------- private: - Qx::GenericError parseCategories(const QList& headingsRow); - Qx::GenericError parseBallot(const QList& ballotRow, qsizetype ballotNum); + RefBallotBoxError parseCategories(const QList& headingsRow); + RefBallotBoxError parseBallot(const QList& ballotRow, qsizetype ballotNum); public: - Qx::GenericError readInto(); + RefBallotBoxError readInto(); }; /*! @endcond */ } diff --git a/lib/src/reference/calculatoroptions_p.cpp b/lib/src/reference/calculatoroptions_p.cpp index 738835a..4a3b7b9 100644 --- a/lib/src/reference/calculatoroptions_p.cpp +++ b/lib/src/reference/calculatoroptions_p.cpp @@ -10,6 +10,28 @@ namespace Star { /*! @cond */ +//=============================================================================================================== +// CalcOptionsError +//=============================================================================================================== + +//-Constructor-------------------------------------------------------------------- +CalcOptionsError::CalcOptionsError(Type t) : + mType(t), + mString(ERR_STRINGS.value(t)) +{} + +//-Instance Functions------------------------------------------------------------- +//Public: +bool CalcOptionsError::isValid() const { return mType != NoError; } +CalcOptionsError::Type CalcOptionsError::type() const { return mType; } +QString CalcOptionsError::string() const { return mString; } + +//Private: +Qx::Severity CalcOptionsError::deriveSeverity() const { return Qx::Critical; } +quint32 CalcOptionsError::deriveValue() const { return mType; } +QString CalcOptionsError::derivePrimary() const { return MAIN_ERR_MSG; } +QString CalcOptionsError::deriveSecondary() const { return mString; } + //=============================================================================================================== // RefCalcOptionsReader @@ -24,23 +46,22 @@ CalcOptionsReader::CalcOptionsReader(Star::Calculator::Options* targetOptions, c //-Instance Functions------------------------------------------------------------------------------------------------- //Public: -Qx::GenericError CalcOptionsReader::readInto() +CalcOptionsError CalcOptionsReader::readInto() { QFileInfo optInfo(mOptionsReader.filePath()); // Before checking the reader status, see if the file even exists if(!optInfo.exists()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_DOES_NOT_EXIST); + return CalcOptionsError(CalcOptionsError::DoesNotExist); // Also, directly check for empty file if(optInfo.size() == 0) - return Qx::GenericError(); + return CalcOptionsError(); // Open file Qx::IoOpReport openReport = mOptionsReader.openFile(); if(openReport.isFailure()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(openReport.outcomeInfo()); - + return CalcOptionsError(CalcOptionsError::IoError, openReport.outcomeInfo()); // Read file line-by-line for(uint line = 0; !mOptionsReader.atEnd(); line++) @@ -56,14 +77,14 @@ Qx::GenericError CalcOptionsReader::readInto() if(potentialOpt.has_value()) mTargetOptions->setFlag(potentialOpt.value()); else - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_INVALID_OPTION.arg(line)); + return CalcOptionsError(CalcOptionsError::InvalidOption, line); } // Check stream status if(mOptionsReader.hasError()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(mOptionsReader.status().outcomeInfo()); + CalcOptionsError(CalcOptionsError::IoError, mOptionsReader.status().outcomeInfo()); - return Qx::GenericError(); + return CalcOptionsError(); } /*! @endcond */ } diff --git a/lib/src/reference/calculatoroptions_p.h b/lib/src/reference/calculatoroptions_p.h index 7cec813..5a7791d 100644 --- a/lib/src/reference/calculatoroptions_p.h +++ b/lib/src/reference/calculatoroptions_p.h @@ -6,7 +6,6 @@ #include // Qx Includes -#include #include // Project Includes @@ -16,17 +15,70 @@ namespace Star { /*! @cond */ -class CalcOptionsReader +class QX_ERROR_TYPE(CalcOptionsError, "Star::CalcOptionsError", 1151) { -//-Class Variables-------------------------------------------------------------------------------------------------- + friend class CalcOptionsReader; +//-Class Enums------------------------------------------------------------- +public: + enum Type + { + NoError, + DoesNotExist, + IoError, + InvalidOption + }; + +//-Class Variables------------------------------------------------------------- +private: + static inline const QString MAIN_ERR_MSG = u"Error reading the options list."_s; + static inline const QHash ERR_STRINGS{ + {NoError, u""_s}, + {NoError, u"IO Error: %1"_s}, + {DoesNotExist, u"The specified file does not exist."_s}, + {InvalidOption, u"The file contains an invalid option (Line: %1)."_s} + }; + +//-Instance Variables------------------------------------------------------------- +private: + Type mType; + QString mString; + +//-Constructor------------------------------------------------------------- private: - static inline const QString MAIN_ERR_MSG = QStringLiteral("Error reading the options list."); + CalcOptionsError(Type t = NoError); - static inline const QString ERR_DOES_NOT_EXIST = QStringLiteral("The specified file does not exist."); - static inline const QString ERR_INVALID_OPTION = QStringLiteral("The file contains an invalid option (Line: %1)."); + template + requires (std::same_as && ...) + CalcOptionsError(Type t, Strings... args) : + CalcOptionsError(t) + { + mString = mString.arg(args...); + } - static inline const Qx::GenericError ERROR_TEMPLATE = Qx::GenericError(Qx::GenericError::Critical, MAIN_ERR_MSG); + template + requires (std::integral && ...) + CalcOptionsError(Type t, Ints... args) : + CalcOptionsError(t) + { + auto sub = [this](auto integer) { mString = mString.arg(integer); }; + (sub(args), ...); + } +//-Instance Functions------------------------------------------------------------- +public: + bool isValid() const; + Type type() const; + QString string() const; + +private: + Qx::Severity deriveSeverity() const override; + quint32 deriveValue() const override; + QString derivePrimary() const override; + QString deriveSecondary() const override; +}; + +class CalcOptionsReader +{ //-Instance Variables-------------------------------------------------------------------------------------------------- private: Star::Calculator::Options* mTargetOptions; @@ -38,7 +90,7 @@ class CalcOptionsReader //-Instance Functions------------------------------------------------------------------------------------------------- public: - Qx::GenericError readInto(); + CalcOptionsError readInto(); }; /*! @endcond */ } diff --git a/lib/src/reference/categoryconfig_p.cpp b/lib/src/reference/categoryconfig_p.cpp index 07339c4..91fb2a5 100644 --- a/lib/src/reference/categoryconfig_p.cpp +++ b/lib/src/reference/categoryconfig_p.cpp @@ -7,6 +7,28 @@ namespace Star { /*! @cond */ +//=============================================================================================================== +// RefCategoryConfigError +//=============================================================================================================== + +//-Constructor-------------------------------------------------------------------- +RefCategoryConfigError::RefCategoryConfigError(Type t) : + mType(t), + mString(ERR_STRINGS.value(t)) +{} + +//-Instance Functions------------------------------------------------------------- +//Public: +bool RefCategoryConfigError::isValid() const { return mType != NoError; } +RefCategoryConfigError::Type RefCategoryConfigError::type() const { return mType; } +QString RefCategoryConfigError::string() const { return mString; } + +//Private: +Qx::Severity RefCategoryConfigError::deriveSeverity() const { return Qx::Critical; } +quint32 RefCategoryConfigError::deriveValue() const { return mType; } +QString RefCategoryConfigError::derivePrimary() const { return MAIN_ERR_MSG; } +QString RefCategoryConfigError::deriveSecondary() const { return mString; } + //=============================================================================================================== // RefCategoryConfig //=============================================================================================================== @@ -38,22 +60,22 @@ RefCategoryConfig::Reader::Reader(RefCategoryConfig* targetConfig, const QString //-Instance Functions------------------------------------------------------------------------------------------------- //Public: -Qx::GenericError RefCategoryConfig::Reader::readInto() +RefCategoryConfigError RefCategoryConfig::Reader::readInto() { QFileInfo iniInfo(mIniReader.filePath()); // Before checking the reader status, see if the file even exists if(!iniInfo.exists()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_DOES_NOT_EXIST); + return RefCategoryConfigError(RefCategoryConfigError::DoesNotExist); // Also, directly check for empty file if(iniInfo.size() == 0) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_EMPTY); + return RefCategoryConfigError(RefCategoryConfigError::Empty); // Open file Qx::IoOpReport openReport = mIniReader.openFile(); if(openReport.isFailure()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(openReport.outcomeInfo()); + return RefCategoryConfigError(RefCategoryConfigError::IoError, openReport.outcomeInfo()); // Set default section Section currentSection = Section::None; @@ -77,16 +99,16 @@ Qx::GenericError RefCategoryConfig::Reader::readInto() else if(iniLine == RefCategoryConfig::SECTION_HEADING_GENERAL) currentSection = Section::General; else - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_INVALID_LAYOUT.arg(line)); + return RefCategoryConfigError(RefCategoryConfigError::InvalidLayout, line); } else if(currentSection == Section::None) // No Section - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_INVALID_INI.arg(line)); + return RefCategoryConfigError(RefCategoryConfigError::InvalidIni, line); else // Key/Value { // Split key/value QStringList keyValueList = iniLine.split('='); if(keyValueList.size() != 2) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_INVALID_INI.arg(line)); + return RefCategoryConfigError(RefCategoryConfigError::InvalidIni, line); QString key = keyValueList.at(0).trimmed(); QString valueStr = keyValueList.at(1).trimmed(); @@ -96,14 +118,14 @@ Qx::GenericError RefCategoryConfig::Reader::readInto() uint value = valueStr.toUInt(&validValue); if(!validValue) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_INVALID_VALUE_TYPE.arg(line)); + return RefCategoryConfigError(RefCategoryConfigError::InvalidValueType, line); // Sections if(currentSection == Section::Categories) { // Ensure value is valid if(value < 2) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_INVALID_CATEGORY_COUNT.arg(line)); + return RefCategoryConfigError(RefCategoryConfigError::InvalidCategoryCount, line); // Make sure this isn't a duplicate auto start = mTargetConfig->headers().constBegin(); @@ -113,7 +135,7 @@ Qx::GenericError RefCategoryConfig::Reader::readInto() }) != end); if(dupe) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_DUPLICATE_CATEGORY.arg(line)); + return RefCategoryConfigError(RefCategoryConfigError::DuplicateCategory, line); // Add header to target config RefCategoryHeader ch{.name = key, .candidateCount = value}; @@ -129,12 +151,12 @@ Qx::GenericError RefCategoryConfig::Reader::readInto() { // Ensure value is valid if(value < 1) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_INVALID_SEAT_COUNT.arg(line)); + return RefCategoryConfigError(RefCategoryConfigError::InvalidSeatCount, line); mTargetConfig->mSeats = value; } else - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_INVALID_GENERAL_KEY.arg(line)); + return RefCategoryConfigError(RefCategoryConfigError::InvalidGeneralKey, line); } else qCritical("Unhandled section"); @@ -143,17 +165,17 @@ Qx::GenericError RefCategoryConfig::Reader::readInto() // Check stream status if(mIniReader.hasError()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(mIniReader.status().outcomeInfo()); + return RefCategoryConfigError(RefCategoryConfigError::IoError, mIniReader.status().outcomeInfo()); // Fail if there are no categories if(mTargetConfig->mHeaders.isEmpty()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_NO_CATEGORIES); + return RefCategoryConfigError(RefCategoryConfigError::NoCategories); // Fail if seat count wasn't specified if(mTargetConfig->mSeats < 1) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_NO_SEATS); + return RefCategoryConfigError(RefCategoryConfigError::NoSeats); - return Qx::GenericError(); + return RefCategoryConfigError(); } /*! @endcond */ } diff --git a/lib/src/reference/categoryconfig_p.h b/lib/src/reference/categoryconfig_p.h index c5d8883..f90042b 100644 --- a/lib/src/reference/categoryconfig_p.h +++ b/lib/src/reference/categoryconfig_p.h @@ -6,7 +6,6 @@ #include // Qx Includes -#include #include namespace Star @@ -19,6 +18,86 @@ struct RefCategoryHeader uint candidateCount; }; +class QX_ERROR_TYPE(RefCategoryConfigError, "Star::RefCategoryConfigError", 1152) +{ + friend class RefCategoryConfig; +//-Class Enums------------------------------------------------------------- +public: + enum Type + { + NoError, + DoesNotExist, + Empty, + IoError, + InvalidIni, + InvalidLayout, + InvalidValueType, + InvalidCategoryCount, + DuplicateCategory, + InvalidGeneralKey, + InvalidSeatCount, + NoCategories, + NoSeats + }; + +//-Class Variables------------------------------------------------------------- +private: + static inline const QString MAIN_ERR_MSG = u"Error reading the category configuration."_s; + static inline const QHash ERR_STRINGS{ + {NoError, u""_s}, + {DoesNotExist, u"The specified file does not exist."_s}, + {Empty, u"The provided file is empty."_s}, + {IoError, u"IO Error: %1"_s}, + {InvalidIni, u"The provided file is not a valid INI format file (Line: %1)."_s}, + {InvalidLayout, u"The provided file does not follow the expected layout (Line: %1)."_s}, + {InvalidValueType, u"Category configuration contains a value that is not an unsigned integer (Line: %1)."_s}, + {InvalidCategoryCount, u"A category specified a candidate count less than 2 (Line: %1)."_s}, + {DuplicateCategory, u"The provided file contains duplicate categories (Line: %1)."_s}, + {InvalidGeneralKey, u"Unrecognized General key (Line: %1)."_s}, + {InvalidSeatCount, u"The provided file specified a seat count less than 1 (Line: %1)."_s}, + {NoCategories, u"The provided file contains no categories."_s}, + {NoSeats, u"The provided file didn't specify a seat count."_s} + }; + +//-Instance Variables------------------------------------------------------------- +private: + Type mType; + QString mString; + +//-Constructor------------------------------------------------------------- +private: + RefCategoryConfigError(Type t = NoError); + + template + requires (std::same_as && ...) + RefCategoryConfigError(Type t, Strings... args) : + RefCategoryConfigError(t) + { + mString = mString.arg(args...); + } + + template + requires (std::integral && ...) + RefCategoryConfigError(Type t, Ints... args) : + RefCategoryConfigError(t) + { + auto sub = [this](auto integer) { mString = mString.arg(integer); }; + (sub(args), ...); + } + +//-Instance Functions------------------------------------------------------------- +public: + bool isValid() const; + Type type() const; + QString string() const; + +private: + Qx::Severity deriveSeverity() const override; + quint32 deriveValue() const override; + QString derivePrimary() const override; + QString deriveSecondary() const override; +}; + class RefCategoryConfig { //-Inner Classes---------------------------------------------------------------------------------------------------- @@ -54,24 +133,6 @@ class RefCategoryConfig::Reader private: enum Section { None, Categories, General }; -//-Class Variables-------------------------------------------------------------------------------------------------- -private: - static inline const QString MAIN_ERR_MSG = QStringLiteral("Error reading the category configuration."); - - static inline const QString ERR_DOES_NOT_EXIST = QStringLiteral("The specified file does not exist."); - static inline const QString ERR_EMPTY = QStringLiteral("The provided file is empty."); - static inline const QString ERR_INVALID_INI = QStringLiteral("The provided file is not a valid INI format file (Line: %1)."); - static inline const QString ERR_INVALID_LAYOUT = QStringLiteral("The provided file does not follow the expected layout (Line: %1)."); - static inline const QString ERR_INVALID_VALUE_TYPE = QStringLiteral("Category configuration contains a value that is not an unsigned integer (Line: %1)."); - static inline const QString ERR_INVALID_CATEGORY_COUNT = QStringLiteral("A category specified a candidate count less than 2 (Line: %1)."); - static inline const QString ERR_DUPLICATE_CATEGORY = QStringLiteral("The provided file contains duplicate categories (Line: %1)."); - static inline const QString ERR_INVALID_GENERAL_KEY = QStringLiteral("Unrecognized General key (Line: %1)."); - static inline const QString ERR_INVALID_SEAT_COUNT = QStringLiteral("The provided file specified a seat count less than 1 (Line: %1)."); - static inline const QString ERR_NO_CATEGORIES = QStringLiteral("The provided file contains no categories."); - static inline const QString ERR_NO_SEATS = QStringLiteral("The provided file didn't specify a seat count."); - - static inline const Qx::GenericError ERROR_TEMPLATE = Qx::GenericError(Qx::GenericError::Critical, MAIN_ERR_MSG); - //-Instance Variables-------------------------------------------------------------------------------------------------- private: RefCategoryConfig* mTargetConfig; @@ -83,7 +144,7 @@ class RefCategoryConfig::Reader //-Instance Functions------------------------------------------------------------------------------------------------- public: - Qx::GenericError readInto(); + RefCategoryConfigError readInto(); }; /*! @endcond */ } diff --git a/lib/src/reference/resultset_p.cpp b/lib/src/reference/resultset_p.cpp index f9f5f73..f297eac 100644 --- a/lib/src/reference/resultset_p.cpp +++ b/lib/src/reference/resultset_p.cpp @@ -10,6 +10,36 @@ #include #include +/* TODO: Somehow (whether adding a way to specify class construction in Qx Json, or other) + * to have the json data parsed directly into the results list + */ +namespace +{ + +struct JsonQualifer +{ + QSet firstAdv; + QSet secondAdv; + + QX_JSON_STRUCT( + firstAdv, + secondAdv + ); +}; + +struct JsonSeat +{ + QString winner; + JsonQualifer qualifier; + + QX_JSON_STRUCT( + winner, + qualifier + ); +}; + +} + namespace Star { /*! @cond */ @@ -26,80 +56,25 @@ ResultSetReader::ResultSetReader(QList* targetList, cons //-Instance Functions------------------------------------------------------------------------------------------------- //Public: -Qx::GenericError ResultSetReader::readInto() +Qx::Error ResultSetReader::readInto() { // Clear return buffer mTargetList->clear(); - // Read file - QByteArray jData; - Qx::IoOpReport readReport = Qx::readBytesFromFile(jData, mFile); - if(readReport.isFailure()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(readReport.outcomeInfo()); + // Parse JSON from file + QList> jsonResults; + Qx::JsonError err = Qx::parseJson(jsonResults, mFile); - // Parse JSON - QJsonParseError jError; - QJsonDocument jDoc = QJsonDocument::fromJson(jData, &jError); - if(jError.error != QJsonParseError::NoError) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(jError.errorString()); - - // Get root value, should be array - if(!jDoc.isArray()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_WRONG_ROOT_TYPE); - QJsonArray jArray = jDoc.array(); - - // Iterate array to fill target list - for(const QJsonValue& value : jArray) + // Load results into target list + for(const auto& res : jsonResults) { - // Get array - if(!value.isArray()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_WRONG_ROOT_ARRAY_ITEM_TYPE); - QJsonArray expectedResultSeatArray = value.toArray(); - - // Iterate seat array to create expected result Star::ExpectedElectionResult::Builder eerb; - for(const QJsonValue& jValueSeat : expectedResultSeatArray) - { - // Get object - if(!jValueSeat.isObject()) - return Qx::GenericError(ERROR_TEMPLATE).setSecondaryInfo(ERR_WRONG_SEAT_ARRAY_ITEM_TYPE); - QJsonObject seatObj = jValueSeat.toObject(); - - // Get expected keys - Qx::GenericError convError; - - QString winner; - QJsonObject jQualifierObj; - if((convError = Qx::Json::checkedKeyRetrieval(winner, seatObj, KEY_WINNER_STR)).isValid()) - return convError; - if((convError = Qx::Json::checkedKeyRetrieval(jQualifierObj, seatObj, KEY_QUALIFIER_OBJ)).isValid()) - return convError; - - // Get expected keys for qualifier - QJsonArray jFirstAdvArray; - QJsonArray jSecondAdvArray; - if((convError = Qx::Json::checkedKeyRetrieval(jFirstAdvArray, jQualifierObj, KEY_QUALIFIER_FIRST_ADV_ARRAY)).isValid()) - return convError; - if((convError = Qx::Json::checkedKeyRetrieval(jSecondAdvArray, jQualifierObj, KEY_QUALIFIER_SECOND_ADV_ARRAY)).isValid()) - return convError; - - // Convert qualifier arrays to sets - QSet firstAdvSet; - QSet secondAdvSet; - if((convError = Qx::Json::checkedArrayConversion(firstAdvSet, jFirstAdvArray)).isValid()) - return convError; - if((convError = Qx::Json::checkedArrayConversion(secondAdvSet, jSecondAdvArray)).isValid()) - return convError; - - // Add seat to builder - eerb.wSeat(Seat(winner, QualifierResult(firstAdvSet, secondAdvSet))); - } - - // Build expected result and add to target list + for(const auto& seat : res) + eerb.wSeat(Seat(seat.winner, QualifierResult(seat.qualifier.firstAdv, seat.qualifier.secondAdv))); mTargetList->append(eerb.build()); } - return Qx::GenericError(); + return Qx::Error(); } /*! @endcond */ } diff --git a/lib/src/reference/resultset_p.h b/lib/src/reference/resultset_p.h index af106cf..1666ddf 100644 --- a/lib/src/reference/resultset_p.h +++ b/lib/src/reference/resultset_p.h @@ -5,7 +5,7 @@ #include // Qx Includes -#include +#include // Project Includes #include "star/expectedelectionresult.h" @@ -15,23 +15,6 @@ namespace Star /*! @cond */ class ResultSetReader { -//-Class Variables-------------------------------------------------------------------------------------------------- -private: - // Keys - static inline const QString KEY_WINNER_STR = QStringLiteral("winner"); - static inline const QString KEY_QUALIFIER_OBJ = QStringLiteral("qualifier"); - static inline const QString KEY_QUALIFIER_FIRST_ADV_ARRAY = QStringLiteral("firstAdv"); - static inline const QString KEY_QUALIFIER_SECOND_ADV_ARRAY = QStringLiteral("secondAdv"); - - // Errors - static inline const QString MAIN_ERR_MSG = QStringLiteral("Error reading results set."); - - static inline const QString ERR_WRONG_ROOT_TYPE = QStringLiteral("Root item is not an array."); - static inline const QString ERR_WRONG_ROOT_ARRAY_ITEM_TYPE = QStringLiteral("Root array did not contain other arrays."); - static inline const QString ERR_WRONG_SEAT_ARRAY_ITEM_TYPE = QStringLiteral("Seat array did not contain objects."); - - static inline const Qx::GenericError ERROR_TEMPLATE = Qx::GenericError(Qx::GenericError::Critical, MAIN_ERR_MSG); - //-Instance Variables-------------------------------------------------------------------------------------------------- private: QList* mTargetList; @@ -43,7 +26,7 @@ class ResultSetReader //-Instance Functions------------------------------------------------------------------------------------------------- public: - Qx::GenericError readInto(); + Qx::Error readInto(); }; /*! @endcond */ } From b00a680b7f5b781fb2819f0592c704c2ae134e0f Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 3 Dec 2023 17:37:50 -0500 Subject: [PATCH 06/18] Fix mainpage MD heading levels --- doc/cmake/file_templates/mainpage.md.in | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/doc/cmake/file_templates/mainpage.md.in b/doc/cmake/file_templates/mainpage.md.in index 236f0f3..21fd5ff 100644 --- a/doc/cmake/file_templates/mainpage.md.in +++ b/doc/cmake/file_templates/mainpage.md.in @@ -22,7 +22,7 @@ Packaging ---------- STAR++ is provided as a CMake package composed of a single library, several public header files, and the reference application. -#### Package Components: +### Package Components: - `Base` - The main library - `Frontend` - The reference application @@ -141,12 +141,13 @@ Alternatively, you can use the `qt-cmake` wrapper for similar Qt environment aut The CMake project is designed to be used with multi-configuration generators such as Visual Studio or Ninja Multi-Config (recommended), and may require some tweaking to work with single configuration generators. -#### CMake Options: +### CMake Options: - `STARPP_DOCS` - Set to `ON` in order to generate the documentation target (OFF) - `STARPP_TESTS` - Set to `ON` in order to generate the test targets (OFF) - `BUILD_SHARED_LIBS` - Build STAR++ as a shared library instead of a static one (OFF) -#### CMake Targets: + +### CMake Targets: - `all` - Builds the STAR++ library and reference application - `install` - Installs the build output into `CMAKE_INSTALL_PREFIX` @@ -155,7 +156,7 @@ The CMake project is designed to be used with multi-configuration generators suc - `starpp_docs` - Builds the STAR++ documentation - `starpp_tst_...` - Builds the various test targets. To actually run tests, just build the general CMake tests target `test`. -#### CMake Install Components: +### CMake Install Components: - `starpp` - Installs top-level files (README.md, CMake package configuration files, etc.) - `starpp_base` - Installs the built library @@ -164,7 +165,8 @@ The CMake project is designed to be used with multi-configuration generators suc If STAR++ is configured as a sub-project, its install components are automatically removed from the `all` component, as to not pollute the install directory of the top-level project. They can still be installed by directly referencing their component names as shown above. -#### Documentation: +### Documentation: + In order for the `starpp_docs` target to be generated the CMake cache variable **STARPP_DOCS** must be set to *ON* when CMake is invoked: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cmake.exe (...) -D STARPP_DOCS=ON @@ -211,10 +213,12 @@ The path for this documentation varies depending on how you obtained Qt, but is # By default on Windows is C:\Program Files\Qt # On Linux it is often /usr/local/Qt -#### Tests: +### Tests: + The project contains a suite of tests to ensure that the library functions as intended. They will be expanded upon as the library matures. -#### Package +### Package: + By default, the CMakeLists project configures CPack to create an artifact ZIP containing: - The library - The reference application From daed0fb3892c024d8629f6c94de652cf5e5f8208 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 3 Dec 2023 17:42:42 -0500 Subject: [PATCH 07/18] Actions: Update Qt and Doxygen --- .github/workflows/build-starpp-linux.yml | 4 ++-- .github/workflows/build-starpp-windows.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-starpp-linux.yml b/.github/workflows/build-starpp-linux.yml index 531dcef..071eb19 100644 --- a/.github/workflows/build-starpp-linux.yml +++ b/.github/workflows/build-starpp-linux.yml @@ -58,7 +58,7 @@ jobs: - name: Install Qt (custom build) uses: oblivioncth/actions/general/install-and-cache-qt-from-ffynnon@dev with: - version: 6.4.2 + version: 6.6.0 os: linux compiler: ${{ matrix.qt_comp }} linkage: ${{ matrix.lib_linkage }} @@ -67,7 +67,7 @@ jobs: - name: Install Doxygen uses: oblivioncth/actions/ubuntu/install-doxygen-from-sourceforge@dev with: - version: 1.9.4 + version: 1.9.8 - name: Install Graphviz run: sudo apt-get install graphviz - name: Install Ninja diff --git a/.github/workflows/build-starpp-windows.yml b/.github/workflows/build-starpp-windows.yml index b074b8b..84ba87c 100644 --- a/.github/workflows/build-starpp-windows.yml +++ b/.github/workflows/build-starpp-windows.yml @@ -43,7 +43,7 @@ jobs: - name: Install Qt (custom build) uses: oblivioncth/actions/general/install-and-cache-qt-from-ffynnon@dev with: - version: 6.4.2 + version: 6.6.0 os: windows compiler: msvc2022 linkage: ${{ matrix.lib_linkage }} @@ -52,7 +52,7 @@ jobs: - name: Install Doxygen uses: oblivioncth/actions/general/cache-and-install-doxygen-from-ffynnon@dev with: - version: 1.9.4 + version: 1.9.8 os: windows credentials: ${{ secrets.qt_ffynnon_cred }} - name: Install Graphviz From c5339292fdd404061e499b3d3b695d32d632e0f8 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 3 Dec 2023 17:53:18 -0500 Subject: [PATCH 08/18] Drop GCC 10 due to ICE --- .github/workflows/build-starpp-linux.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-starpp-linux.yml b/.github/workflows/build-starpp-linux.yml index 071eb19..e60c45f 100644 --- a/.github/workflows/build-starpp-linux.yml +++ b/.github/workflows/build-starpp-linux.yml @@ -18,14 +18,9 @@ jobs: fail-fast: false matrix: os: [ubuntu-20.04, ubuntu-22.04] - compiler: [gcc, clang] + compiler: [clang] lib_linkage: [shared, static] include: - - os: ubuntu-20.04 - compiler: gcc - c_comp: gcc-10 - cxx_comp: g++-10 - qt_comp: clang12 - os: ubuntu-20.04 compiler: clang c_comp: clang-12 @@ -36,6 +31,13 @@ jobs: c_comp: gcc-12 cxx_comp: g++-12 qt_comp: clang14 + lib_linkage: shared + - os: ubuntu-22.04 + compiler: gcc + c_comp: gcc-12 + cxx_comp: g++-12 + qt_comp: clang14 + lib_linkage: static - os: ubuntu-22.04 compiler: clang c_comp: clang-14 From 56e60ed1117a5ba06b820b243ac2bd97a1320d5a Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 3 Dec 2023 17:57:21 -0500 Subject: [PATCH 09/18] Actions: Add workaround for actions/runner-images/issues/8659 --- .github/workflows/build-starpp-linux.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/build-starpp-linux.yml b/.github/workflows/build-starpp-linux.yml index e60c45f..386eca4 100644 --- a/.github/workflows/build-starpp-linux.yml +++ b/.github/workflows/build-starpp-linux.yml @@ -66,6 +66,15 @@ jobs: linkage: ${{ matrix.lib_linkage }} path: ${{ env.qt_install_dir }} credentials: ${{ secrets.qt_ffynnon_cred }} + - name: Update package index + run: sudo apt-get update + - name: WORKAROUND FOR https://github.com/actions/runner-images/issues/8659 + if: matrix.os == 'ubuntu-22.04' + run: | + echo "TEMPORARY WORKAROUND FOR GITHUB RUNNER BUG #8659\n\nRemoving GCC 13 as it breaks Clang14" + sudo rm -f /etc/apt/sources.list.d/ubuntu-toolchain-r-ubuntu-test-jammy.list + sudo apt-get update + sudo apt-get install -y --allow-downgrades libc6=2.35-0ubuntu3.4 libc6-dev=2.35-0ubuntu3.4 libstdc++6=12.3.0-1ubuntu1~22.04 libgcc-s1=12.3.0-1ubuntu1~22.04 - name: Install Doxygen uses: oblivioncth/actions/ubuntu/install-doxygen-from-sourceforge@dev with: From 7c6017fb70acd4530f39a691c6e0bc6a40184bc1 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 3 Dec 2023 18:02:50 -0500 Subject: [PATCH 10/18] Actions: Install EGL on 22.04 --- .github/workflows/build-starpp-linux.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build-starpp-linux.yml b/.github/workflows/build-starpp-linux.yml index 386eca4..af4b065 100644 --- a/.github/workflows/build-starpp-linux.yml +++ b/.github/workflows/build-starpp-linux.yml @@ -89,6 +89,9 @@ jobs: run: sudo apt-get install libxkbcommon-x11-dev libxcb-*-dev - name: Install OpenGL lib run: sudo apt-get install libglu1-mesa-dev # TODO: See if this can be avoided, for some reason qhelpgenerator needs this, maybe its because it was available during compilation + - name: Install EGL [22.04] + if: matrix.os == 'ubuntu-22.04' + run: sudo apt-get install libegl1-mesa-dev - name: Checkout STARpp uses: actions/checkout@v3 with: From ea974b7e8a383ce8c8ac00d4555cbfa215003d4e Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 3 Dec 2023 18:12:07 -0500 Subject: [PATCH 11/18] Update CMake max --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 733ffd8..0645f2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ #================= Project Setup ========================== # CMake -cmake_minimum_required(VERSION 3.23.0...3.25.0) +cmake_minimum_required(VERSION 3.23.0...3.26.0) # Project # NOTE: DON'T USE TRAILING ZEROS IN VERSIONS From 6e80461bf7d1c7a9fb51c6604e872272d10ad438 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Mon, 4 Dec 2023 11:34:27 -0500 Subject: [PATCH 12/18] Post missing paths error instead of just logging --- app/src/core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/core.cpp b/app/src/core.cpp index 6b6c2e5..291dfaf 100644 --- a/app/src/core.cpp +++ b/app/src/core.cpp @@ -187,7 +187,7 @@ Qx::Error Core::initialize() else { CoreError err(CoreError::InvalidArgs, ERR_MISSING_REF_PATHS); - logError(NAME, err); + postError(NAME, err); return err; } From 51cf1a3fe3c44fb571cfd3f5dfa00a6cb6c234f0 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Mon, 4 Dec 2023 13:44:16 -0500 Subject: [PATCH 13/18] Use one-indexing for winners in resultspresenter.cpp --- app/src/core.h | 2 +- app/src/resultspresenter.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/core.h b/app/src/core.h index bba6953..05caf73 100644 --- a/app/src/core.h +++ b/app/src/core.h @@ -119,7 +119,7 @@ class Core : public QObject /* NOTE: This will cause a compilation error when changing Star::Calculator::Options in order to prompt the developer * to ensure any new options have been described above and then manually check them off here */ -# + static_assert(magic_enum::enum_values() == std::array{ Star::Calculator::NoOptions, Star::Calculator::AllowTrueTies, diff --git a/app/src/resultspresenter.cpp b/app/src/resultspresenter.cpp index e7898cb..a4708c0 100644 --- a/app/src/resultspresenter.cpp +++ b/app/src/resultspresenter.cpp @@ -58,7 +58,7 @@ void ResultPresenter::printElectionResult(const Star::ElectionResult& result) const QStringList winners = result.winners(); cout << HEADING_WINNERS << endl; for(qsizetype w = 0; w < winners.size(); w++) - cout << WINNER_TEMPLATE.arg(w).arg(winners.at(w)) << endl; + cout << WINNER_TEMPLATE.arg(w + 1).arg(winners.at(w)) << endl; cout << endl; if(!result.isComplete()) From 31ba6fbf219963b5396e0a0509593c156fb0de77 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Mon, 4 Dec 2023 13:55:07 -0500 Subject: [PATCH 14/18] Move face-off stats updates to dedicated function --- lib/src/headtoheadresults.cpp | 33 ++++++++++++++++----------------- lib/src/headtoheadresults.h | 3 +++ 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/src/headtoheadresults.cpp b/lib/src/headtoheadresults.cpp index 3ae035b..2e913ad 100644 --- a/lib/src/headtoheadresults.cpp +++ b/lib/src/headtoheadresults.cpp @@ -43,28 +43,27 @@ HeadToHeadResults::HeadToHeadResults(const Election* election) prefB++; } - // Update stats for candidate A - CandidateStats& statsA = mStats[opponentA]; - if(prefA > prefB) - statsA.victories.insert(opponentB); - else if(prefA < prefB) - statsA.defeats.insert(opponentB); - statsA.preferences.increase(opponentB, prefA); - statsA.antiPreferences.increase(opponentB, prefB); - - // Update stats for candidate B - CandidateStats& statsB = mStats[opponentB]; - if(prefB > prefA) - statsB.victories.insert(opponentA); - else if(prefB < prefA) - statsB.defeats.insert(opponentA); - statsB.preferences.increase(opponentA, prefB); - statsB.antiPreferences.increase(opponentA, prefA); + // Update stats for candidates + faceOffStatsUpdate(opponentA, prefA, opponentB, prefB); + faceOffStatsUpdate(opponentB, prefB, opponentA, prefA); } } } //-Instance Functions------------------------------------------------------------------------------------------------- +//Private: +void HeadToHeadResults::faceOffStatsUpdate(const QString& can, int canPref, const QString& opp, int oppPref) +{ + // Update stats for candidate based on results of face-off with opponent + CandidateStats& cStats = mStats[can]; + if(canPref > oppPref) + cStats.victories.insert(opp); + else if(oppPref < canPref) + cStats.defeats.insert(opp); + cStats.preferences.increase(opp, canPref); + cStats.antiPreferences.increase(opp, oppPref); +} + //Public: int HeadToHeadResults::wins(const QString& candidate) const { diff --git a/lib/src/headtoheadresults.h b/lib/src/headtoheadresults.h index 774546e..bdaae08 100644 --- a/lib/src/headtoheadresults.h +++ b/lib/src/headtoheadresults.h @@ -43,6 +43,9 @@ class HeadToHeadResults HeadToHeadResults(const Election* election); //-Instance Functions------------------------------------------------------------------------------------------------- +private: + void faceOffStatsUpdate(const QString& can, int canPref, const QString& opp, int oppPref); + public: int wins(const QString& candidate) const; int losses(const QString& candidate) const; From 095a38741259f8c5ef880fb093f75a97f099ca52 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Mon, 4 Dec 2023 14:02:21 -0500 Subject: [PATCH 15/18] Update doxygen theme --- .../doxygen-awesome-darkmode-toggle.js | 2 +- .../doxygen-awesome-fragment-copy-button.js | 2 +- .../doxygen-awesome-paragraph-link.js | 2 +- ...n-awesome-sidebar-only-darkmode-toggle.css | 2 +- .../doxygen-awesome-sidebar-only.css | 3 +- .../theme/doxygen-awesome/doxygen-awesome.css | 563 ++++++++++++++---- 6 files changed, 467 insertions(+), 107 deletions(-) diff --git a/doc/res/theme/doxygen-awesome/doxygen-awesome-darkmode-toggle.js b/doc/res/theme/doxygen-awesome/doxygen-awesome-darkmode-toggle.js index f2c5853..40fe2d3 100644 --- a/doc/res/theme/doxygen-awesome/doxygen-awesome-darkmode-toggle.js +++ b/doc/res/theme/doxygen-awesome/doxygen-awesome-darkmode-toggle.js @@ -5,7 +5,7 @@ https://github.com/jothepro/doxygen-awesome-css MIT License -Copyright (c) 2021 - 2022 jothepro +Copyright (c) 2021 - 2023 jothepro Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/doc/res/theme/doxygen-awesome/doxygen-awesome-fragment-copy-button.js b/doc/res/theme/doxygen-awesome/doxygen-awesome-fragment-copy-button.js index 7d06b34..86c16fd 100644 --- a/doc/res/theme/doxygen-awesome/doxygen-awesome-fragment-copy-button.js +++ b/doc/res/theme/doxygen-awesome/doxygen-awesome-fragment-copy-button.js @@ -5,7 +5,7 @@ https://github.com/jothepro/doxygen-awesome-css MIT License -Copyright (c) 2022 jothepro +Copyright (c) 2022 - 2023 jothepro Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/doc/res/theme/doxygen-awesome/doxygen-awesome-paragraph-link.js b/doc/res/theme/doxygen-awesome/doxygen-awesome-paragraph-link.js index 6424dbd..e53d132 100644 --- a/doc/res/theme/doxygen-awesome/doxygen-awesome-paragraph-link.js +++ b/doc/res/theme/doxygen-awesome/doxygen-awesome-paragraph-link.js @@ -5,7 +5,7 @@ https://github.com/jothepro/doxygen-awesome-css MIT License -Copyright (c) 2022 jothepro +Copyright (c) 2022 - 2023 jothepro Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/doc/res/theme/doxygen-awesome/doxygen-awesome-sidebar-only-darkmode-toggle.css b/doc/res/theme/doxygen-awesome/doxygen-awesome-sidebar-only-darkmode-toggle.css index b988b6f..d207446 100644 --- a/doc/res/theme/doxygen-awesome/doxygen-awesome-sidebar-only-darkmode-toggle.css +++ b/doc/res/theme/doxygen-awesome/doxygen-awesome-sidebar-only-darkmode-toggle.css @@ -6,7 +6,7 @@ https://github.com/jothepro/doxygen-awesome-css MIT License -Copyright (c) 2021 jothepro +Copyright (c) 2021 - 2023 jothepro Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/doc/res/theme/doxygen-awesome/doxygen-awesome-sidebar-only.css b/doc/res/theme/doxygen-awesome/doxygen-awesome-sidebar-only.css index 656ebbf..853f6d6 100644 --- a/doc/res/theme/doxygen-awesome/doxygen-awesome-sidebar-only.css +++ b/doc/res/theme/doxygen-awesome/doxygen-awesome-sidebar-only.css @@ -5,7 +5,7 @@ https://github.com/jothepro/doxygen-awesome-css MIT License -Copyright (c) 2021 jothepro +Copyright (c) 2021 - 2023 jothepro Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -81,6 +81,7 @@ html { .ui-resizable-handle { cursor: default; width: 1px !important; + background: var(--separator-color); box-shadow: 0 calc(-2 * var(--top-height)) 0 0 var(--separator-color); } diff --git a/doc/res/theme/doxygen-awesome/doxygen-awesome.css b/doc/res/theme/doxygen-awesome/doxygen-awesome.css index ca6f0bc..ac7f060 100644 --- a/doc/res/theme/doxygen-awesome/doxygen-awesome.css +++ b/doc/res/theme/doxygen-awesome/doxygen-awesome.css @@ -5,7 +5,7 @@ https://github.com/jothepro/doxygen-awesome-css MIT License -Copyright (c) 2021 - 2022 jothepro +Copyright (c) 2021 - 2023 jothepro Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -74,26 +74,27 @@ html { --content-line-height: 27px; /* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/ --content-maxwidth: 1050px; + --table-line-height: 24px; --toc-sticky-top: var(--spacing-medium); --toc-width: 200px; --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 85px); /* colors for various content boxes: @warning, @note, @deprecated @bug */ - --warning-color: #f8d1cc; - --warning-color-dark: #b61825; - --warning-color-darker: #75070f; - --note-color: #faf3d8; - --note-color-dark: #f3a600; - --note-color-darker: #5f4204; - --todo-color: #e4f3ff; - --todo-color-dark: #1879C4; - --todo-color-darker: #274a5c; + --warning-color: #faf3d8; + --warning-color-dark: #f3a600; + --warning-color-darker: #5f4204; + --note-color: #e4f3ff; + --note-color-dark: #1879C4; + --note-color-darker: #274a5c; + --todo-color: #e4dafd; + --todo-color-dark: #5b2bdd; + --todo-color-darker: #2a0d72; --deprecated-color: #ecf0f3; --deprecated-color-dark: #5b6269; --deprecated-color-darker: #43454a; - --bug-color: #e4dafd; - --bug-color-dark: #5b2bdd; - --bug-color-darker: #2a0d72; + --bug-color: #f8d1cc; + --bug-color-dark: #b61825; + --bug-color-darker: #75070f; --invariant-color: #d8f1e3; --invariant-color-dark: #44b86f; --invariant-color-darker: #265532; @@ -159,7 +160,7 @@ html { --toc-background: var(--side-nav-background); --toc-foreground: var(--side-nav-foreground); - /* height of an item in any tree / collapsable table */ + /* height of an item in any tree / collapsible table */ --tree-item-height: 30px; --memname-font-size: var(--code-font-size); @@ -168,6 +169,8 @@ html { --webkit-scrollbar-size: 7px; --webkit-scrollbar-padding: 4px; --webkit-scrollbar-color: var(--separator-color); + + --animation-duration: .12s } @media screen and (max-width: 767px) { @@ -207,21 +210,21 @@ html { --blockquote-background: #222325; --blockquote-foreground: #7e8c92; - --warning-color: #2e1917; - --warning-color-dark: #ad2617; - --warning-color-darker: #f5b1aa; - --note-color: #3b2e04; - --note-color-dark: #f1b602; - --note-color-darker: #ceb670; - --todo-color: #163750; - --todo-color-dark: #1982D2; - --todo-color-darker: #dcf0fa; + --warning-color: #3b2e04; + --warning-color-dark: #f1b602; + --warning-color-darker: #ceb670; + --note-color: #163750; + --note-color-dark: #1982D2; + --note-color-darker: #dcf0fa; + --todo-color: #2a2536; + --todo-color-dark: #7661b3; + --todo-color-darker: #ae9ed6; --deprecated-color: #2e323b; --deprecated-color-dark: #738396; --deprecated-color-darker: #abb0bd; - --bug-color: #2a2536; - --bug-color-dark: #7661b3; - --bug-color-darker: #ae9ed6; + --bug-color: #2e1917; + --bug-color-dark: #ad2617; + --bug-color-darker: #f5b1aa; --invariant-color: #303a35; --invariant-color-dark: #76ce96; --invariant-color-darker: #cceed5; @@ -268,21 +271,21 @@ html.dark-mode { --blockquote-background: #222325; --blockquote-foreground: #7e8c92; - --warning-color: #2e1917; - --warning-color-dark: #ad2617; - --warning-color-darker: #f5b1aa; - --note-color: #3b2e04; - --note-color-dark: #f1b602; - --note-color-darker: #ceb670; - --todo-color: #163750; - --todo-color-dark: #1982D2; - --todo-color-darker: #dcf0fa; + --warning-color: #3b2e04; + --warning-color-dark: #f1b602; + --warning-color-darker: #ceb670; + --note-color: #163750; + --note-color-dark: #1982D2; + --note-color-darker: #dcf0fa; + --todo-color: #2a2536; + --todo-color-dark: #7661b3; + --todo-color-darker: #ae9ed6; --deprecated-color: #2e323b; --deprecated-color-dark: #738396; --deprecated-color-darker: #abb0bd; - --bug-color: #2a2536; - --bug-color-dark: #7661b3; - --bug-color-darker: #ae9ed6; + --bug-color: #2e1917; + --bug-color-dark: #ad2617; + --bug-color-darker: #f5b1aa; --invariant-color: #303a35; --invariant-color-dark: #76ce96; --invariant-color-darker: #cceed5; @@ -307,20 +310,27 @@ body { font-size: var(--page-font-size); } -body, table, div, p, dl, #nav-tree .label, .title, .sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname, .SelectItem, #MSearchField, .navpath li.navelem a, .navpath li.navelem a:hover { +body, table, div, p, dl, #nav-tree .label, .title, +.sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname, +.SelectItem, #MSearchField, .navpath li.navelem a, +.navpath li.navelem a:hover, p.reference, p.definition { font-family: var(--font-family); } h1, h2, h3, h4, h5 { - margin-top: .9em; + margin-top: 1em; font-weight: 600; line-height: initial; } -p, div, table, dl { +p, div, table, dl, p.reference, p.definition { font-size: var(--page-font-size); } +p.reference, p.definition { + color: var(--page-secondary-foreground-color); +} + a:link, a:visited, a:hover, a:focus, a:active { color: var(--primary-color) !important; font-weight: 500; @@ -406,6 +416,10 @@ a.anchor { margin-bottom: -1px; } +.main-menu-btn-icon, .main-menu-btn-icon:before, .main-menu-btn-icon:after { + background: var(--page-secondary-foreground-color); +} + @media screen and (max-width: 767px) { .sm-dox a span.sub-arrow { background: var(--code-background); @@ -540,12 +554,21 @@ a.anchor { margin-top: 0; } -.left #MSearchSelect { +/* until Doxygen 1.9.4 */ +.left img#MSearchSelect { left: 0; user-select: none; padding-left: 8px; } +/* Doxygen 1.9.5 */ +.left span#MSearchSelect { + left: 0; + user-select: none; + margin-left: 8px; + padding: 0; +} + .left #MSearchSelect[src$=".png"] { padding-left: 0 } @@ -662,6 +685,15 @@ html.dark-mode iframe#MSearchResults { filter: invert() hue-rotate(180deg); } +#MSearchResults .SRPage { + background-color: transparent; +} + +#MSearchResults .SRPage .SREntry { + font-size: 10pt; + padding: var(--spacing-small) var(--spacing-medium); +} + #MSearchSelectWindow { border: 1px solid var(--separator-color); border-radius: var(--border-radius-medium); @@ -718,6 +750,7 @@ html.dark-mode iframe#MSearchResults { overflow: auto; transform: translate(0, 20px); animation: ease-out 280ms slideInSearchResultsMobile; + width: auto !important; } /* @@ -745,6 +778,8 @@ html.dark-mode iframe#MSearchResults { #side-nav { padding: 0 !important; background: var(--side-nav-background); + min-width: 8px; + max-width: 50vw; } @media screen and (max-width: 767px) { @@ -759,6 +794,7 @@ html.dark-mode iframe#MSearchResults { #nav-tree { background: transparent; + margin-right: 1px; } #nav-tree .label { @@ -831,8 +867,9 @@ html.dark-mode iframe#MSearchResults { } .ui-resizable-e { - background: var(--separator-color); - width: 1px; + width: 4px; + background: transparent; + box-shadow: inset -1px 0 0 0 var(--separator-color); } /* @@ -846,7 +883,8 @@ div.header { } @media screen and (min-width: 1000px) { - #doc-content > div > div.contents { + #doc-content > div > div.contents, + .PageDoc > div.contents { display: flex; flex-direction: row-reverse; flex-wrap: nowrap; @@ -878,7 +916,7 @@ div.headertitle { div.header .title { font-weight: 600; - font-size: 210%; + font-size: 225%; padding: var(--spacing-medium) var(--spacing-large); word-break: break-word; } @@ -924,8 +962,9 @@ div.contents div.dyncontent { html:not(.light-mode) div.contents > table img, html:not(.light-mode) div.contents div.dyncontent iframe, html:not(.light-mode) div.contents center iframe, - html:not(.light-mode) div.contents table iframe { - filter: hue-rotate(180deg) invert(); + html:not(.light-mode) div.contents table iframe, + html:not(.light-mode) div.contents .dotgraph iframe { + filter: brightness(89%) hue-rotate(180deg) invert(); } } @@ -934,8 +973,10 @@ html.dark-mode div.contents center img, html.dark-mode div.contents > table img, html.dark-mode div.contents div.dyncontent iframe, html.dark-mode div.contents center iframe, -html.dark-mode div.contents table iframe { - filter: hue-rotate(180deg) invert(); +html.dark-mode div.contents table iframe, +html.dark-mode div.contents .dotgraph iframe + { + filter: brightness(89%) hue-rotate(180deg) invert(); } h2.groupheader { @@ -950,14 +991,18 @@ h2.groupheader { -500px 0 var(--page-background-color), 500px 0.75px var(--separator-color), -500px 0.75px var(--separator-color), - 1500px 0 var(--page-background-color), - -1500px 0 var(--page-background-color), - 1500px 0.75px var(--separator-color), - -1500px 0.75px var(--separator-color), - 2000px 0 var(--page-background-color), - -2000px 0 var(--page-background-color), - 2000px 0.75px var(--separator-color), - -2000px 0.75px var(--separator-color); + 900px 0 var(--page-background-color), + -900px 0 var(--page-background-color), + 900px 0.75px var(--separator-color), + -900px 0.75px var(--separator-color), + 1400px 0 var(--page-background-color), + -1400px 0 var(--page-background-color), + 1400px 0.75px var(--separator-color), + -1400px 0.75px var(--separator-color), + 1900px 0 var(--page-background-color), + -1900px 0 var(--page-background-color), + 1900px 0.75px var(--separator-color), + -1900px 0.75px var(--separator-color); } blockquote { @@ -1009,16 +1054,32 @@ table.params .paramname { font-family: var(--font-family-monospace); font-size: var(--code-font-size); padding-right: var(--spacing-small); + line-height: var(--table-line-height); } -.glow { - text-shadow: 0 0 15px var(--primary-light-color) !important; +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px var(--primary-light-color); } .alphachar a { color: var(--page-foreground-color); } +.dotgraph { + max-width: 100%; + overflow-x: scroll; +} + +.dotgraph .caption { + position: sticky; + left: 0; +} + +/* Wrap Graphviz graphs with the `interactive_dotgraph` class if `INTERACTIVE_SVG = YES` */ +.interactive_dotgraph .dotgraph iframe { + max-width: 100%; +} + /* Table of Contents */ @@ -1046,6 +1107,12 @@ div.toc h3 { div.toc li { padding: 0; background: none; + line-height: var(--toc-font-size); + margin: var(--toc-font-size) 0 0 0; +} + +div.toc li::before { + display: none; } div.toc ul { @@ -1067,15 +1134,6 @@ div.toc li a.aboveActive { } -div.toc ul li.level1 { - margin: 0; -} - -div.toc ul li.level2, div.toc ul li.level3 { - margin-top: 0; -} - - @media screen and (max-width: 999px) { div.contents .toc { max-height: 45vh; @@ -1104,6 +1162,7 @@ div.toc ul li.level2, div.toc ul li.level3 { background-color: var(--toc-background); margin: 0; padding: var(--spacing-large) 0; + display: block; } div.contents .toc.interactive > h3::before { @@ -1112,13 +1171,12 @@ div.toc ul li.level2, div.toc ul li.level3 { height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; - border-top: 7px solid var(--primary-color); - margin-top: 5px; - display: block; - float: left; + border-top: 5px solid var(--primary-color); + display: inline-block; margin-right: var(--spacing-small); + margin-bottom: calc(var(--navigation-font-size) / 4); transform: rotate(-90deg); - transition: transform 0.25s ease-out; + transition: transform var(--animation-duration) ease-out; } div.contents .toc.interactive.open > h3::before { @@ -1175,9 +1233,13 @@ div.fragment, pre.fragment { .contents > div.fragment, .textblock > div.fragment, .textblock > pre.fragment, + .textblock > .tabbed > ul > li > div.fragment, + .textblock > .tabbed > ul > li > pre.fragment, .contents > .doxygen-awesome-fragment-wrapper > div.fragment, .textblock > .doxygen-awesome-fragment-wrapper > div.fragment, - .textblock > .doxygen-awesome-fragment-wrapper > pre.fragment { + .textblock > .doxygen-awesome-fragment-wrapper > pre.fragment, + .textblock > .tabbed > ul > li > .doxygen-awesome-fragment-wrapper > div.fragment, + .textblock > .tabbed > ul > li > .doxygen-awesome-fragment-wrapper > pre.fragment { margin: var(--spacing-medium) calc(0px - var(--spacing-large)); border-radius: 0; border-left: 0; @@ -1267,8 +1329,18 @@ div.fragment span.lineno a { color: var(--fragment-link) !important; } -div.fragment .line:first-child .lineno { +div.fragment > .line:first-child .lineno { box-shadow: -999999px 0px 0 999999px var(--fragment-linenumber-background), -999998px 0px 0 999999px var(--fragment-linenumber-border); + background-color: var(--fragment-linenumber-background) !important; +} + +div.line { + border-radius: var(--border-radius-small); +} + +div.line.glow { + background-color: var(--primary-light-color); + box-shadow: none; } /* @@ -1279,7 +1351,7 @@ dl.bug dt a, dl.deprecated dt a, dl.todo dt a { font-weight: bold !important; } -dl.warning, dl.attention, dl.note, dl.deprecated, dl.bug, dl.invariant, dl.pre, dl.todo, dl.remark { +dl.warning, dl.attention, dl.note, dl.deprecated, dl.bug, dl.invariant, dl.pre, dl.post, dl.todo, dl.remark { padding: var(--spacing-medium); margin: var(--spacing-medium) 0; color: var(--page-background-color); @@ -1318,8 +1390,8 @@ dl.todo { color: var(--todo-color-darker); } -dl.todo dt { - color: var(--todo-color-dark); +dl.todo dt a { + color: var(--todo-color-dark) !important; } dl.bug dt a { @@ -1350,13 +1422,13 @@ dl.section dd, dl.bug dd, dl.deprecated dd, dl.todo dd { margin-inline-start: 0px; } -dl.invariant, dl.pre { +dl.invariant, dl.pre, dl.post { background: var(--invariant-color); border-left: 8px solid var(--invariant-color-dark); color: var(--invariant-color-darker); } -dl.invariant dt, dl.pre dt { +dl.invariant dt, dl.pre dt, dl.post dt { color: var(--invariant-color-dark); } @@ -1390,7 +1462,6 @@ div.memitem { div.memproto, h2.memtitle { background: var(--fragment-background); - text-shadow: none; } h2.memtitle { @@ -1466,6 +1537,7 @@ div.memproto table.memname { font-family: var(--font-family-monospace); color: var(--page-foreground-color); font-size: var(--memname-font-size); + text-shadow: none; } div.memproto div.memtemplate { @@ -1473,6 +1545,7 @@ div.memproto div.memtemplate { color: var(--primary-dark-color); font-size: var(--memname-font-size); margin-left: 2px; + text-shadow: none; } table.mlabels, table.mlabels > tbody { @@ -1559,6 +1632,10 @@ table.doxtable tbody { border-radius: var(--border-radius-small); } +table.markdownTable, table.doxtable, table.fieldtable { + padding: 1px; +} + table.doxtable caption { display: block; } @@ -1649,6 +1726,15 @@ table.markdownTable tr:last-child, table.doxtable tr:last-child { border-bottom: none; } +.full_width_table table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) { + display: block; +} + +.full_width_table table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody { + display: table; + width: 100%; +} + table.fieldtable th { font-size: var(--page-font-size); font-weight: 600; @@ -1689,6 +1775,7 @@ table.memberdecls tr[class^='memitem'] .memTemplParams { font-family: var(--font-family-monospace); font-size: var(--code-font-size); color: var(--primary-dark-color); + white-space: normal; } table.memberdecls .memItemLeft, @@ -1714,7 +1801,7 @@ table.memberdecls .memTemplParams { border-left: 1px solid var(--separator-color); border-right: 1px solid var(--separator-color); border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; - padding-bottom: 0; + padding-bottom: var(--spacing-small); } table.memberdecls .memTemplItemLeft { @@ -1726,6 +1813,7 @@ table.memberdecls .memTemplItemLeft { table.memberdecls .memTemplItemRight { border-radius: 0 0 var(--border-radius-small) 0; border-right: 1px solid var(--separator-color); + padding-left: 0; border-top: 0; } @@ -1750,6 +1838,11 @@ table.memberdecls .mdescLeft, table.memberdecls .mdescRight { padding: var(--spacing-small) 0; } +table.memberdecls .memItemLeft, +table.memberdecls .memTemplItemLeft { + padding-right: var(--spacing-medium); +} + table.memberdecls .memSeparator { background: var(--page-background-color); height: var(--spacing-large); @@ -1764,30 +1857,41 @@ table.memberdecls .groupheader { table.memberdecls .inherit_header td { padding: 0 0 var(--spacing-medium) 0; text-indent: -12px; - line-height: 1.5em; color: var(--page-secondary-foreground-color); } -table.memberdecls img[src="closed.png"], table.memberdecls img[src="open.png"] { +table.memberdecls img[src="closed.png"], +table.memberdecls img[src="open.png"], +div.dynheader img[src="open.png"], +div.dynheader img[src="closed.png"] { width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; - border-top: 7px solid var(--primary-color); + border-top: 5px solid var(--primary-color); margin-top: 8px; display: block; float: left; - margin-right: var(--spacing-small); margin-left: -10px; + transition: transform var(--animation-duration) ease-out; +} + +table.memberdecls img { margin-right: 10px; - transition: transform 0.25s ease-out; } -table.memberdecls img[src="closed.png"] { +table.memberdecls img[src="closed.png"], +div.dynheader img[src="closed.png"] { transform: rotate(-90deg); } +.compoundTemplParams { + font-family: var(--font-family-monospace); + color: var(--primary-dark-color); + font-size: var(--code-font-size); +} + @media screen and (max-width: 767px) { table.memberdecls .memItemLeft, @@ -1804,6 +1908,7 @@ table.memberdecls img[src="closed.png"] { border-right: none; border-left: none; border-radius: 0; + white-space: normal; } table.memberdecls .memItemLeft, @@ -1818,7 +1923,7 @@ table.memberdecls img[src="closed.png"] { } table.memberdecls .mdescLeft { - margin-top: calc(0px - var(--page-font-size)); + margin-bottom: calc(0px - var(--page-font-size)); } table.memberdecls .memItemRight, @@ -1916,8 +2021,25 @@ table.directory { width: 100%; } -table.directory td.entry { - padding: var(--spacing-small); +table.directory td.entry, table.directory td.desc { + padding: calc(var(--spacing-small) / 2) var(--spacing-small); + line-height: var(--table-line-height); +} + +table.directory tr.even td:last-child { + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; +} + +table.directory tr.even td:first-child { + border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); +} + +table.directory tr.even:last-child td:last-child { + border-radius: 0 var(--border-radius-small) 0 0; +} + +table.directory tr.even:last-child td:first-child { + border-radius: var(--border-radius-small) 0 0 0; } table.directory td.desc { @@ -1928,6 +2050,10 @@ table.directory tr.even { background-color: var(--odd-color); } +table.directory tr.odd { + background-color: transparent; +} + .icona { width: auto; height: auto; @@ -1936,14 +2062,20 @@ table.directory tr.even { .icon { background: var(--primary-color); - width: 18px; - height: 18px; - line-height: 18px; + border-radius: var(--border-radius-small); + font-size: var(--page-font-size); + padding: calc(var(--page-font-size) / 5); + line-height: var(--page-font-size); + transform: scale(0.8); + height: auto; + width: var(--page-font-size); + user-select: none; } .iconfopen, .icondoc, .iconfclosed { background-position: center; margin-bottom: 0; + height: var(--table-line-height); } .icondoc { @@ -1976,6 +2108,10 @@ html.dark-mode .iconfopen, html.dark-mode .iconfclosed { border-radius: var(--border-radius-small); } +.classindex dl.even { + background-color: transparent; +} + /* Class Index Doxygen 1.8 */ @@ -2101,7 +2237,10 @@ div.memproto::-webkit-scrollbar, .contents center::-webkit-scrollbar, .contents .center::-webkit-scrollbar, .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar, -div.contents .toc::-webkit-scrollbar { +div.contents .toc::-webkit-scrollbar, +.contents .dotgraph::-webkit-scrollbar, +.contents .tabs-overview-container::-webkit-scrollbar { + background: transparent; width: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); height: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); } @@ -2113,7 +2252,9 @@ div.memproto::-webkit-scrollbar-thumb, .contents center::-webkit-scrollbar-thumb, .contents .center::-webkit-scrollbar-thumb, .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-thumb, -div.contents .toc::-webkit-scrollbar-thumb { +div.contents .toc::-webkit-scrollbar-thumb, +.contents .dotgraph::-webkit-scrollbar-thumb, +.contents .tabs-overview-container::-webkit-scrollbar-thumb { background-color: transparent; border: var(--webkit-scrollbar-padding) solid transparent; border-radius: calc(var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); @@ -2127,7 +2268,9 @@ div.memproto:hover::-webkit-scrollbar-thumb, .contents center:hover::-webkit-scrollbar-thumb, .contents .center:hover::-webkit-scrollbar-thumb, .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody:hover::-webkit-scrollbar-thumb, -div.contents .toc:hover::-webkit-scrollbar-thumb { +div.contents .toc:hover::-webkit-scrollbar-thumb, +.contents .dotgraph:hover::-webkit-scrollbar-thumb, +.contents .tabs-overview-container:hover::-webkit-scrollbar-thumb { background-color: var(--webkit-scrollbar-color); } @@ -2138,7 +2281,9 @@ div.memproto::-webkit-scrollbar-track, .contents center::-webkit-scrollbar-track, .contents .center::-webkit-scrollbar-track, .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-track, -div.contents .toc::-webkit-scrollbar-track { +div.contents .toc::-webkit-scrollbar-track, +.contents .dotgraph::-webkit-scrollbar-track, +.contents .tabs-overview-container::-webkit-scrollbar-track { background: transparent; } @@ -2175,7 +2320,9 @@ div.memproto, .contents center, .contents .center, .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, -div.contents .toc { +div.contents .toc, +.contents .dotgraph, +.contents .tabs-overview-container { scrollbar-width: thin; } @@ -2204,7 +2351,7 @@ doxygen-awesome-dark-mode-toggle { } doxygen-awesome-dark-mode-toggle > svg { - transition: transform .1s ease-in-out; + transition: transform var(--animation-duration) ease-in-out; } doxygen-awesome-dark-mode-toggle:active > svg { @@ -2289,7 +2436,7 @@ a.anchorlink { text-decoration: none; opacity: .15; display: none; - transition: opacity .1s ease-in-out, color .1s ease-in-out; + transition: opacity var(--animation-duration) ease-in-out, color var(--animation-duration) ease-in-out; } a.anchorlink svg { @@ -2308,3 +2455,215 @@ a.anchorlink:hover { h2:hover a.anchorlink, h1:hover a.anchorlink, h3:hover a.anchorlink, h4:hover a.anchorlink { display: inline-block; } + +/* + Optional tab feature +*/ + +.tabbed ul { + padding-inline-start: 0px; + margin: 0; + padding: var(--spacing-small) 0; +} + +.tabbed li { + display: none; +} + +.tabbed li.selected { + display: block; +} + +.tabs-overview-container { + overflow-x: auto; + display: block; + overflow-y: visible; +} + +.tabs-overview { + border-bottom: 1px solid var(--separator-color); + display: flex; + flex-direction: row; +} + +@media screen and (max-width: 767px) { + .tabs-overview-container { + margin: 0 calc(0px - var(--spacing-large)); + } + .tabs-overview { + padding: 0 var(--spacing-large) + } +} + +.tabs-overview button.tab-button { + color: var(--page-foreground-color); + margin: 0; + border: none; + background: transparent; + padding: calc(var(--spacing-large) / 2) 0; + display: inline-block; + font-size: var(--page-font-size); + cursor: pointer; + box-shadow: 0 1px 0 0 var(--separator-color); + position: relative; + + -webkit-tap-highlight-color: transparent; +} + +.tabs-overview button.tab-button .tab-title::before { + display: block; + content: attr(title); + font-weight: 600; + height: 0; + overflow: hidden; + visibility: hidden; +} + +.tabs-overview button.tab-button .tab-title { + float: left; + white-space: nowrap; + font-weight: normal; + padding: calc(var(--spacing-large) / 2) var(--spacing-large); + border-radius: var(--border-radius-medium); + transition: background-color var(--animation-duration) ease-in-out, font-weight var(--animation-duration) ease-in-out; +} + +.tabs-overview button.tab-button:not(:last-child) .tab-title { + box-shadow: 8px 0 0 -7px var(--separator-color); +} + +.tabs-overview button.tab-button:hover .tab-title { + background: var(--separator-color); + box-shadow: none; +} + +.tabs-overview button.tab-button.active .tab-title { + font-weight: 600; +} + +.tabs-overview button.tab-button::after { + content: ''; + display: block; + position: absolute; + left: 0; + bottom: 0; + right: 0; + height: 0; + width: 0%; + margin: 0 auto; + border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; + background-color: var(--primary-color); + transition: width var(--animation-duration) ease-in-out, height var(--animation-duration) ease-in-out; +} + +.tabs-overview button.tab-button.active::after { + width: 100%; + box-sizing: border-box; + height: 3px; +} + + +/* + Navigation Buttons +*/ + +.section_buttons:not(:empty) { + margin-top: calc(var(--spacing-large) * 3); +} + +.section_buttons table.markdownTable { + display: block; + width: 100%; +} + +.section_buttons table.markdownTable tbody { + display: table !important; + width: 100%; + box-shadow: none; + border-spacing: 10px; +} + +.section_buttons table.markdownTable td { + padding: 0; +} + +.section_buttons table.markdownTable th { + display: none; +} + +.section_buttons table.markdownTable tr.markdownTableHead { + border: none; +} + +.section_buttons tr th, .section_buttons tr td { + background: none; + border: none; + padding: var(--spacing-large) 0 var(--spacing-small); +} + +.section_buttons a { + display: inline-block; + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + color: var(--page-secondary-foreground-color) !important; + text-decoration: none; + transition: color var(--animation-duration) ease-in-out, background-color var(--animation-duration) ease-in-out; +} + +.section_buttons a:hover { + color: var(--page-foreground-color) !important; + background-color: var(--odd-color); +} + +.section_buttons tr td.markdownTableBodyLeft a { + padding: var(--spacing-medium) var(--spacing-large) var(--spacing-medium) calc(var(--spacing-large) / 2); +} + +.section_buttons tr td.markdownTableBodyRight a { + padding: var(--spacing-medium) calc(var(--spacing-large) / 2) var(--spacing-medium) var(--spacing-large); +} + +.section_buttons tr td.markdownTableBodyLeft a::before, +.section_buttons tr td.markdownTableBodyRight a::after { + color: var(--page-secondary-foreground-color) !important; + display: inline-block; + transition: color .08s ease-in-out, transform .09s ease-in-out; +} + +.section_buttons tr td.markdownTableBodyLeft a::before { + content: '〈'; + padding-right: var(--spacing-large); +} + + +.section_buttons tr td.markdownTableBodyRight a::after { + content: '〉'; + padding-left: var(--spacing-large); +} + + +.section_buttons tr td.markdownTableBodyLeft a:hover::before { + color: var(--page-foreground-color) !important; + transform: translateX(-3px); +} + +.section_buttons tr td.markdownTableBodyRight a:hover::after { + color: var(--page-foreground-color) !important; + transform: translateX(3px); +} + +@media screen and (max-width: 450px) { + .section_buttons a { + width: 100%; + box-sizing: border-box; + } + + .section_buttons tr td:nth-of-type(1).markdownTableBodyLeft a { + border-radius: var(--border-radius-medium) 0 0 var(--border-radius-medium); + border-right: none; + } + + .section_buttons tr td:nth-of-type(2).markdownTableBodyRight a { + border-radius: 0 var(--border-radius-medium) var(--border-radius-medium) 0; + } +} From c855928848e3cca148019852b47e5959443dedc3 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Tue, 5 Dec 2023 06:38:10 +0000 Subject: [PATCH 16/18] Fix face-off stats update --- lib/src/headtoheadresults.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/headtoheadresults.cpp b/lib/src/headtoheadresults.cpp index 2e913ad..3404de5 100644 --- a/lib/src/headtoheadresults.cpp +++ b/lib/src/headtoheadresults.cpp @@ -58,7 +58,7 @@ void HeadToHeadResults::faceOffStatsUpdate(const QString& can, int canPref, cons CandidateStats& cStats = mStats[can]; if(canPref > oppPref) cStats.victories.insert(opp); - else if(oppPref < canPref) + else if(oppPref > canPref) cStats.defeats.insert(opp); cStats.preferences.increase(opp, canPref); cStats.antiPreferences.increase(opp, oppPref); From 8740131d711c78b7477e43f6214a4ee72e0f6e38 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sat, 16 Dec 2023 20:27:54 -0500 Subject: [PATCH 17/18] Bump --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0645f2f..a8b074c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.23.0...3.26.0) # Project # NOTE: DON'T USE TRAILING ZEROS IN VERSIONS project(STARpp - VERSION 0.2.1 + VERSION 0.2.2 LANGUAGES CXX DESCRIPTION "C++ implementation of STAR voting" ) From 489a03ed68a6e84c9f494808bdce78bb27f63a9d Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sat, 16 Dec 2023 20:40:29 -0500 Subject: [PATCH 18/18] Actions: Bump fix for runner GCC version issue. --- .github/workflows/build-starpp-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-starpp-linux.yml b/.github/workflows/build-starpp-linux.yml index af4b065..b418cf5 100644 --- a/.github/workflows/build-starpp-linux.yml +++ b/.github/workflows/build-starpp-linux.yml @@ -74,7 +74,7 @@ jobs: echo "TEMPORARY WORKAROUND FOR GITHUB RUNNER BUG #8659\n\nRemoving GCC 13 as it breaks Clang14" sudo rm -f /etc/apt/sources.list.d/ubuntu-toolchain-r-ubuntu-test-jammy.list sudo apt-get update - sudo apt-get install -y --allow-downgrades libc6=2.35-0ubuntu3.4 libc6-dev=2.35-0ubuntu3.4 libstdc++6=12.3.0-1ubuntu1~22.04 libgcc-s1=12.3.0-1ubuntu1~22.04 + sudo apt-get install -y --allow-downgrades libc6=2.35-0ubuntu3.5 libc6-dev=2.35-0ubuntu3.5 libstdc++6=12.3.0-1ubuntu1~22.04 libgcc-s1=12.3.0-1ubuntu1~22.04 - name: Install Doxygen uses: oblivioncth/actions/ubuntu/install-doxygen-from-sourceforge@dev with: