FLOSS Project Planets

The Drop Times: Brad Jones on Modernizing Drupal's Data Management with JSON Integration

Planet Drupal - 11 hours 33 min ago
Brad Jones, a digital nomad and seasoned Drupal developer, merges his technical expertise and unique experiences as a part-time paramedic. His proposal, "JSON Data and Schemas FTW!", aims to revolutionize Drupal's data management by integrating JSON data types. Recognized at DrupalCon Pittsburgh's Pitch-burgh Innovation Contest, this initiative seeks to enhance flexibility and interoperability within Drupal.
Categories: FLOSS Project Planets

1xINTERNET blog: How to optimise team efficiency by reducing "Work in Progress"

Planet Drupal - 13 hours 42 min ago

Work in Progress (WIP) is a well-known concept for optimising efficiency in various business processes. It is straightforward to understand and apply. In this article, we will show you how, and give examples how we apply it with a team of around 100 colleagues.

Categories: FLOSS Project Planets

mark.ie: My Drupal Core Contributions for week-ending July 26th, 2024

Planet Drupal - 13 hours 42 min ago

Here's what I've been working on for my Drupal contributions this week. Thanks to Code Enigma for sponsoring the time to work on these.

Categories: FLOSS Project Planets

Web Review, Week 2024-30

Planet KDE - 15 hours 26 sec ago

Let’s go for my web review for the week 2024-30.

On Open Source and the Sustainability of the Commons

Tags: tech, foss, licensing, sustainability, commons, politics

It’s a piece which really resonates with me. I’ve been thinking and saying for a while that focusing mostly on the technical (licensing and dev) aspects of Open Source was a mistake. This completely overlooked the political side of the Free Software equation. This is why the industry is as it is now. We need stronger commons and indeed the AGPL is best for that.

https://ploum.net/2024-07-01-opensource_sustainability.html


2024 Stack Overflow Developer Survey

Tags: tech, programming

A few surprises in there but otherwise it feels a bit like a repeat from last year. I keep being dismayed at how low the ethical concern of the energy impact of generative AI scores in this survey.

https://survey.stackoverflow.co/2024/


Microsoft says 8.5M systems hit by CrowdStrike BSOD, releases USB recovery tool | Ars Technica

Tags: tech, windows, safety

The cleanup of that mess is still on-going. A bit more automation would help.

https://arstechnica.com/information-technology/2024/07/microsoft-says-8-5m-systems-hit-by-crowdstrike-bsod-releases-usb-recovery-tool/


The Backlash Against AI Scraping Is Real and Measurable

Tags: tech, ai, machine-learning, gpt, criticism

Content creators are clearly annoyed at the lack of consent. The more technical ones are trying to take the matter in their own hands.

https://www.404media.co/the-backlash-against-ai-scraping-is-real-and-measurable/


Astronomers discover technique to spot AI fakes using galaxy-measurement tools

Tags: tech, ai, machine-learning, gpt, graphics, astronomy, physics

Still not perfect, but that’s an interesting development.

https://arstechnica.com/information-technology/2024/07/astronomers-discover-technique-to-spot-ai-fakes-using-galaxy-measurement-tools/


AI models collapse when trained on recursively generated data | Nature

Tags: tech, data, ai, machine-learning, gpt, research

More discussion about models collapse. The provenance of data will become a crucial factor to our ability to train further models.

https://www.nature.com/articles/s41586-024-07566-y


How a North Korean Fake IT Worker Tried to Infiltrate Us

Tags: tech, security, hiring, remote-working

Interesting story. This is getting harder to hire for remote positions I guess.

https://blog.knowbe4.com/how-a-north-korean-fake-it-worker-tried-to-infiltrate-us


Secure Boot is completely broken on 200+ models from 5 big device makers | Ars Technica

Tags: tech, bios, security, hardware

A reminder that Secure Boot is worth nothing if the device makers don’t manage cryptographic keys properly…

https://arstechnica.com/security/2024/07/secure-boot-is-completely-compromised-on-200-models-from-5-big-device-makers/


Give Me the Green Light Part 1: Hacking Traffic Control Systems — Red Threat

Tags: tech, transportation, security

Make sure to read also part 2. You’d expect critical infrastructure like this to not be exposed over the Internet, and to be properly protected…

https://www.redthreatsec.com/blog/greenlightspart1


Automerge CRDT

Tags: tech, crdt, rust, javascript

Need to make a realtime collaboration application? This might come in handy.

https://automerge.org/


NAS Performance: NFS vs. SMB vs. SSHFS | Jake’s Blog

Tags: tech, networking, storage, benchmarking

Interesting comparisons, some of it was a bit unexpected to me. I didn’t expect SSHFS to be that OK.

https://blog.ja-ke.tech/2019/08/27/nas-performance-sshfs-nfs-smb.html


libfaketime modifies the system time for a single application

Tags: tech, time, tests, tools

This can definitely come in handy. I can see myself using it for testing behaviors in the past or the future on a real application. This should also help writing automated tests in some cases.

https://github.com/wolfcw/libfaketime


Does C++ allow template specialization by concepts? – Daniel Lemire’s blog

Tags: tech, c++

This is indeed a shame. It’d be nice to not add all the concepts you plan on supporting in the class declaration…

https://lemire.me/blog/2024/07/22/does-c-allow-template-specialization-by-concepts/


What’s the point of std::monostate? You can’t do anything with it!

Tags: tech, c++, type-systems

There’s a good reason to have it in the standard. As mentioned in this post it can help with std::variant.

https://devblogs.microsoft.com/oldnewthing/20240708-00/?p=109959


PsyArXiv Preprints | Psychological Affordances Can Provide a Missing Explanatory Layer for Why Interventions to Improve Developer Experience Take Hold or Fail

Tags: tech, psychology, developer-experience

Interesting preprint review. Not sure I got it all in depth, will definitely need to revisit it at some point.

https://osf.io/preprints/psyarxiv/qz43x


Bye for now!

Categories: FLOSS Project Planets

Promet Source: Provus®Gov vs CivicPlus for Local Government

Planet Drupal - 15 hours 34 min ago
Takeaway: Provus®Gov emerges as the superior choice for forward-thinking government entities. Powered by Drupal, Provus®Gov as an open-source, plug-and-play platform offers unmatched flexibility, scalability, and advanced features that grow with your needs. Its user-friendly interface empowers non-technical staff, while robust security measures and built-in accessibility compliance ensure your site meets the highest standards.
Categories: FLOSS Project Planets

KDE Human Interface Guidelines update

Planet KDE - 19 hours 38 min ago

It’s been about a month and a half since I wrote about KDE’s new Human Interface Guidelines (HIG). It turns out there’s a surprising amount to report since then!

First of all, the news got picked up by Linux Magazine which did a story about it, including an interview with me! That felt nice.

Next, there have been a number of contributions and enhancements:

Joshua Goins
  • Fixed a lot of typos, awkward wordings, and small errors.
  • Added information about using Qt to set Task Manager badges directly.
  • Expanded the instructions on contributing to the HIG.
Thiago Sueto
  • Corrected several typos and spelling errors.
Christoph Wolk
  • Improved the grammatical correctness of one of the text recommendations.
Nate Graham (me)
  • Polished up the text some more.
  • Added additional suggested inclusiveness-related text replacements.
  • Clarified when a hamburger menu is and isn’t appropriate.
  • Updated the icon size recommendations.
  • Added examples and suggested replacements for common acronyms.
  • Wrote a recommendation for how to implement “go home” navigation.
  • Mentioned when first-run wizards are and aren’t appropriate, migrating some content from our old “Frequently discussed topics” wiki page.
  • Refined the recommendation for button length and combox text capitalization.
  • Described when it’s appropriate to shorten button labels because nearby context indicates what they affect.
  • Expanded the Icons page to offer more concrete guidelines about how to choose an icon and what style to use, and also added more pictures.

Overall I think it’s looking pretty good now, especially the Icons page which received a lot of attention recently.

In addition, there are more pending merge requests by Christoph Wolk, Emir Sari, and me. So it feels like an actual team project now! I think the goal of encouraging more contribution can be called a success.

Finally, Christoph Wolk and I have been going through System Settings pages and tweaking them to comply with the HIG. System Settings is good low-hanging fruit since it’s almost all QML at this point, so changes are easy. And there are a lot of pages, so it’s not hard to find small inconsistencies.

But were not finished yet! More eyeballs are needed. A few TODOs need resolving. More images could be helpful. So check out these two links to learn how to contribute changes:

Even a beginner developer can help out by tweaking the user interface to conform to the HIG. And if you’re a hardcore developer, we still need some more components for writing powerful QML apps.

Still too scary? Then donate to KDE. Our budget is tiny, so your money genuinely does have an impact!

Categories: FLOSS Project Planets

eiriksm.dev: Getting rid of cronner.module

Planet Drupal - Thu, 2024-07-25 21:49

Background: This blog post is part 2 of musings around legacy code on violinist.io. Violinist.io is an automated dependency updater for PHP/Composer. It's a SaaS built on Drupal 8, now running on Drupal 10, in its eigth year. In this second post I am looking at one way to approach legacy code, and how to use static analysis and test driven development to safely refactor and remove legacy code.

Some months ago I wrote about the combined feeling of shame and respect that surrounds legacy code. In an attempt to get rid of the legacy code in what is called cronner.module, I will start from the top of the .module file, and work my way towards removing it completely. From time to time, that can also result in a good blog post, I thought. Here's a blog post about that.

The first lines of the module file is this:

<?php /** * @file * Cronner module. * * Bad name, but what are you going to do, right? */

The code here sounds a bit resigned when it asks about what are you going to do. But in this blog post, what are we going to do? We will start the process of getting rid of all of it, that's what we will do!

The first few lines of actual code are constant definitions. Here's the first one:

define('CRONNER_STATE_KEY_PREFIX', 'cronner_state.node.');

So far we can speculate, but it seems to be a prefix. And it's used for storing some state about nodes. Defining constants like this might seem strange if you are a bit new to Drupal, but this way of defining constants was canonical in Drupal 7 and below, but also followed a lot of codebases into the Drupal 8 era. Drupal core as well actually. One such example is the constant FILE_EXISTS_RENAME which lived on until Drupal 9 (deprecated in 8.7.0). Anyway I digress.

What we want then, is to remove this one constant. Let's just try that and see what breaks? Here's the output from phpunit:

There were 19 errors: … Error: Undefined constant "CRONNER_STATE_KEY_PREFIX”

The unit tests are failing. 19 of them. Good start, we have decent unit test coverage. Let's see if our integration tests fail?

xxx scenarios (xx passed, 112 failed) xxxx steps (xxxx passed, 49 failed, xxx skipped) xxmxx.xxs (90.59Mb)

112 scenarios failed in our behat test suite. Great indication that we can remove things safely! Lastly let's do some static analysis with PHPStan:

Line web/modules/custom/cronner/cronner.module ------ --------------------------------------------------------------------- xxx Constant CRONNER_STATE_KEY_PREFIX not found.

As expected, PHPStan also informs me about this change being a problem. Thanks PHPStan! It also indicates that among the scanned files, the constant is only used once. It's used like this:

/** * Gets the state key of a node. */ function _cronner_get_state_key(NodeInterface $node) { return CRONNER_STATE_KEY_PREFIX . $node->id(); }

In addition to the comment being very little helpful, this tells me I have just encountered another part of the cronner module to remove. Let's remove this entire function as well since we already know the function must be covered by both unit tests and integration tests. Then let’s go ahead and use a combination of TDD and static analysis (with PHPStan) to make sure our refactoring is successful. I remove the function and re-run PHPStan:

Function _cronner_get_state_key not found. … [ERROR] Found 7 errors

PHPStan is helpfully pointing out all of the 7 places I should start with the refactoring. I look through some of them and see the usages are quite connected to some of the other constants in the beginning of the file:

define('CRONNER_PROJECT_NEW', 'new'); define('CRONNER_PROJECT_QUEUED', 'queued'); define('CRONNER_PROJECT_RUNNING', 'running'); define('CRONNER_PROJECT_PROCESSED', 'processed'); define('CRONNER_PROJECT_ERRORED', 'errored'); define('CRONNER_PROJECT_UNKNOWN', 'unknown');

My mother always used to say. When you are tidying up your room it’s best to keep going while you are somewhat effective in deciding what to get rid of. If you find some of your old toys and start to play with them, it’s an indication that the tidying session is heading towards an unproductive state. And right now I feel effective and decide right away I am removing those constants as well. I guess that also makes the analogy to me tidying my room as a kid kind of weird, since the opposite would mean these constants were my toys, and I end up playing with them? I mean, I do end up playing with old code from time to time, but constants? No fun playing with.

But looking at these old toys, it also becomes obvious what we use these constants for. Node state could mean all kinds of things, right? This is used to store and update the job status of the projects. Like if they are currently queued, if they are currently running and so on.

So it turns out that while removing this, this actually seems like a good opportunity to clean up some of that code and make it a bit more modern. What I usually do when cleaning up custom code like this is to put as much as possible on drupal.org as open source code. This is the case now as well. So I open an issue to create a project run status service, and start to refactor the custom code and logic surrounding the removals of constants and functions in cronner.module. It can be found here: https://www.drupal.org/project/violinist_projects/issues/3453459.

Now I go ahead and start using this service. It quickly becomes obvious that some of the constants are also used in a map to display a human readable status to the user:

/** * Gets a human readable version of a status constant. * * @param string $status * A status constant. * * @return string * Something more sensible. */ function cronner_get_human_status($status) { $map = [ CRONNER_PROJECT_UNKNOWN => t('Unknown'), CRONNER_PROJECT_ERRORED => t('Errored'), CRONNER_PROJECT_PROCESSED => t('Processed'), CRONNER_PROJECT_RUNNING => t('Running'), CRONNER_PROJECT_NEW => t('New'), CRONNER_PROJECT_QUEUED => t('Queued'), ]; return !empty($map[$status]) ? $map[$status] : $status; }

There’s also methods for getting a state from a node, and setting it. Which I am also removing, and finding usages of in static analysis:

xxx Function cronner_set_state not found. 💡 Learn more at https://phpstan.org/user-guide/discovering-symbols xxx Function _cronner_get_state_key not found. 💡 Learn more at https://phpstan.org/user-guide/discovering-symbols xxx Function cronner_get_human_status not found. 💡 Learn more at https://phpstan.org/user-guide/discovering-symbols

Or in unit tests like so:

ReplaceTokensTest::testClaimJobAndTokenReplaced Error: Call to undefined function cronner_set_state()

Instead of these calls to getting the state, setting the state, and getting the human readable state, I am now using the newly created service. When I started writing this blog post I was very much looking forward to summarizing the numbers of deleted lines and how great that was, but in practice some of the changes are actually adding lines to the module:

- cronner_set_state($node, CRONNER_PROJECT_PROCESSED); + /** @var \Drupal\violinist_projects\ProjectRunStatus $run_status_service */ + $run_status_service = \Drupal::service('violinist_projects.run_status'); + $run_status_service->setRunStatusForProject($node, ProjectRunStatusValue::STATUS_PROCESSED);

Jokes aside. After some successful deletions and refactorings into using a service I am looking at 99 deletions and 55 additions. A net positive result I would say. Unfortunately there is still quite a way to go before I can go ahead and delete the entire folder called “cronner”. But at least I managed to refactor the codebase and delete the first 7 lines of constants in the file.

To celebrate this tiny step towards getting rid of cronner.module I tried to search for cronner on giphy. No hits, at this point. Oh well, here is an animated gif that supposedly illustrates “cronn”

 

Categories: FLOSS Project Planets

GSoC'24 Okular | Week 4-8 Recap

Planet KDE - Thu, 2024-07-25 13:30

The past weeks involved a lot of work surrounding the implementation of Acrobat specific methods for processing form fields, added support for different types of form widgets and some UI improvements were made or are being worked upon. A detailed list of MRs merged and raised is described below.

MRs merged:
  • AFTime_Keystroke implementation : This method implementation specifies what input keystrokes are allowed in a form field accepting time information. !MR987
  • AFSpecial_Keystroke implementation : This method implementation specifies what input keystrokes are allowed in form fields of special type i.e. those that accept as input phone numbers, ssn and zip codes. !MR1013
  • AFPercent_Keystroke and AFNumber_Keystroke methods implemented : These methods specify input keystrokes for percents and numerical data. !MR988
  • Implement AFDate_KeystrokeEx and AFDate_FormatEx methods. : For correctly accepting input dates and formatting them according to some pre-specified format. !MR1017
  • Global object implementation : A very basic implementation of global object that allows users to read and write to the global object. Persistence and subscription not supported as of now. !MR1016
  • Commit values and restore: Implemented the feature to restore values to the previous committed value upon entering a value that is rejected by a keystroke action.!MR985
  • Fix numerical interpretation in form fields: Calculations were suffering from a major bug 474661 that caused incorrect results when using different locales. This was fixed in the !MR992. The MR focused on how numerical values should be interpreted in form fields.
  • Implemented DocClose, DocWillPrint, DocDidPrint, DocWillSave and DocDidSave events: Now actions are triggered during these events with the changes introduced in the !MR1019.
  • Radio Buttons and Check Boxes size fix: Now radio buttons and check boxes are painted with correct size and resized when zooming to provide a better user experience. !MR1015
  • Implement value (getter), numItems, currentValueIndices properties and getItemAt for FormFieldChoices: These methods were introduced to improve the functionality of FormFieldChoices. !MR1031
  • ResetForm functionality in Poppler: The Reset form functionality was added to the Qt frontend in Poppler. Introduced in this commit

Along with these, more MRs are under works for things like implementing UI experience when using form fields and extending functionality of different types of form fields and actions.

See you next time. Cheers!

Categories: FLOSS Project Planets

libtool @ Savannah: libtool-2.5.1 released [beta]

GNU Planet! - Thu, 2024-07-25 11:18

Libtoolers!

The Libtool Team is pleased to announce the release of libtool 2.5.1, a beta release.

GNU Libtool hides the complexity of using shared libraries behind a
consistent, portable interface. GNU Libtool ships with GNU libltdl, which
hides the complexity of loading dynamic runtime libraries (modules)
behind a consistent, portable interface.

There have been 33 commits by 8 people in the 10 weeks since 2.5.0.

See the NEWS below for a brief summary.

Thanks to everyone who has contributed!
The following people contributed changes to this release:

  Bruno Haible (3)
  Ileana Dumitrescu (24)
  Julien ÉLIE (1)
  Khem Raj (1)
  Peter Kokot (1)
  Richard Purdie (1)
  Vincent Lefevre (1)
  trcrsired (1)

Ileana
 [on behalf of the libtool maintainers]
==================================================================

Here is the GNU libtool home page:
    https://gnu.org/s/libtool/

For a summary of changes and contributors, see:
  https://git.sv.gnu.org/gitweb/?p=libtool.git;a=shortlog;h=v2.5.1
or run this command from a git-cloned libtool directory:
  git shortlog v2.5.0..v2.5.1

Here are the compressed sources:
  https://alpha.gnu.org/gnu/libtool/libtool-2.5.1.tar.gz   (1.9MB)
  https://alpha.gnu.org/gnu/libtool/libtool-2.5.1.tar.xz   (1020KB)

Here are the GPG detached signatures:
  https://alpha.gnu.org/gnu/libtool/libtool-2.5.1.tar.gz.sig
  https://alpha.gnu.org/gnu/libtool/libtool-2.5.1.tar.xz.sig

Use a mirror for higher download bandwidth:
  https://www.gnu.org/order/ftp.html

Here are the SHA1 and SHA256 checksums:

  5e2f00be5b616b0a6120b2947e562b8448e139b2  libtool-2.5.1.tar.gz
  aoPtr9QtTi69wJV5+ZzoKNX5MvFzjeAklcyMKITkMM4=  libtool-2.5.1.tar.gz
  9f72b896f593c4f81cdd6c20c9d99463663e48a9  libtool-2.5.1.tar.xz
  0oDmTIzb8UXXb7kbOyGe2rAb20PLmUAuSsuX0BAGNv0=  libtool-2.5.1.tar.xz

Verify the base64 SHA256 checksum with cksum -a sha256 --check
from coreutils-9.2 or OpenBSD's cksum since 2007.

Use a .sig file to verify that the corresponding file (without the
.sig suffix) is intact.  First, be sure to download both the .sig file
and the corresponding tarball.  Then, run a command like this:

  gpg --verify libtool-2.5.1.tar.gz.sig

The signature should match the fingerprint of the following key:

  pub   rsa4096 2021-09-23 [SC]
        FA26 CA78 4BE1 8892 7F22  B99F 6570 EA01 146F 7354
  uid   Ileana Dumitrescu <ileanadumi95@protonmail.com>
  uid   Ileana Dumitrescu <ileanadumitrescu95@gmail.com>

If that command fails because you don't have the required public key,
or that public key has expired, try the following commands to retrieve
or refresh it, and then rerun the 'gpg --verify' command.

  gpg --locate-external-key ileanadumi95@protonmail.com

  gpg --recv-keys 6570EA01146F7354

  wget -q -O- 'https://savannah.gnu.org/project/release-gpgkeys.php?group=libtool&download=1' | gpg --import -

As a last resort to find the key, you can try the official GNU
keyring:

  wget -q https://ftp.gnu.org/gnu/gnu-keyring.gpg
  gpg --keyring gnu-keyring.gpg --verify libtool-2.5.1.tar.gz.sig

This release was bootstrapped with the following tools:
  Autoconf 2.72e
  Automake 1.17
  Gnulib v1.0-563-gd3efdd55f3

NEWS

  • Noteworthy changes in release 2.5.1 (2024-07-25) [beta]


** New features:

  - Support C++17 compilers in the C++ tests.

  - Add sysroot to library path for cross builds.

** Important incompatible changes:

  - Autoconf 2.64 is required for libtool.m4 to use AS_VAR_APPEND.

** Bug fixes:

  - Fix for uninitialized variable in libtoolize.

  - Skip Fortran/C demo tests when using Clang with fsanitize to
    avoid an incompatible ASan runtime.

  - Updated documentation for testing.

  - Fix failing test to account for program-prefix usage.

  - Replaced a deprecated macro to remove warning messages in the
    testsuite logs.

  - Fix number of arguments for AC_CHECK_PROG call.

  - Fix test failures with no-canonical-prefixes flag by checking
    if the flag is supported first.

  - Fix test failures with no-undefined flag by checking host OS
    before appending the flag.

  - Skip test when passing CXX flags through libtool to avoid test
    failure on NetBSD.

  - Remove texinfo warning for period in node name of pxref.

  - Alter syntax in sed command to fix numerous test failures
    on 64-bit windows/cygwin/mingw.

  - Fix 'Wstrict-prototypes' warnings.

  - Correct DLL Installation Path for mingw multilib builds.

  - Fix '--preserve-dup-deps' stripping duplicates.

  - Disable chained fixups for macOS, since it is not compatible with
    '-undefined dynamic_lookup'.

** Changes in supported systems or compilers:

  - Support additional flang-based compilers, 'flang-new' and 'ftn'.


Enjoy!

Categories: FLOSS Project Planets

The Drop Times: A Look Back: Highlights from DrupalCamp Asheville 2024

Planet Drupal - Thu, 2024-07-25 10:10
Reflecting on DrupalCamp Asheville 2024, the event featured a vibrant mix of workshops, sessions, and social activities. April Sides, the event organizer, highlighted the emphasis on inclusivity and community building in her conversation with The DropTimes. Attendees enjoyed hands-on learning experiences, an interactive Unconference, and a scenic hike in the Blue Ridge Mountains, making it a memorable event for all. The organizers plan to expand outreach to local educational institutions in future events to grow the Drupal community further.
Categories: FLOSS Project Planets

mark.ie: My LocalGov Drupal contributions for week-ending July 26th, 2024

Planet Drupal - Thu, 2024-07-25 09:14

Here's what I've been working on for my LocalGov Drupal contributions this week. Thanks to Big Blue Door for sponsoring the time to work on these.

Categories: FLOSS Project Planets

Tag1 Consulting: Migrating Your Data from D7 to D10: Migrating content types

Planet Drupal - Thu, 2024-07-25 09:14

This step-by-step series has covered a lot of ground on planning and preparing for a Drupal 7 to Drupal 10 migration. Today, we start putting that knowledge into practice by automatically migrating content types. First, we will execute a migration to pull all content types in Drupal 7. Then, we will customize the migration to remove unnecessary content types. Finally, we will learn how a separate node title label migration also affects content type configuration in Drupal 10.

Read more mauricio Thu, 07/25/2024 - 06:32
Categories: FLOSS Project Planets

Drupal Association blog: FAQs About Drupal 7's End of Life

Planet Drupal - Thu, 2024-07-25 09:09

As Drupal 7's end-of-life (EOL) approaches on 5 January 2025, many users have questions about what this means for their Drupal websites and what steps they need to take. Here, we address the most frequently asked questions to help you navigate this transition.

What does end-of-life mean for Drupal 7?

End-of-life (EOL) means that Drupal 7 will no longer receive security updates, fixes, or official support from the Drupal community after 5 January 2025. This will impact the security, compliance, and functionality of any site that continues to run on Drupal 7.

Why is Drupal 7 being retired?

Drupal 7 will be 14 years old when it reaches the end of life. That's a long time in the software world. Drupal 7 is being retired to allow the Drupal community to focus on newer versions built with a more modern architecture and more advanced capabilitie. This shift ensures that resources are directed towards maintaining and innovating the more modern versions of Drupal, including the Drupal Starshot intiative.

What are the key dates I need to know?
  • 23 February 2022: Announcement of Drupal 7 EOL extension.
  • 1 August 2023: Commencement of reduced support for moderately critical issues, alongside other support changes.
  • 5 January 2025: Official end-of-life date for Drupal 7.
How will security support change?

Once Drupal 7 reaches its EOL, no further security advisories or updates will be provided. If you must remain on Drupal 7, we recommend opting for a commercial vendor who offers extended support. HeroDevs Drupal 7 Never-Ending Support (NES), is the first such offering available. This service is a seamless drop-in replacement for Drupal 7, providing your site with ongoing security updates, compliance support, and compatibility fixes past end-of-life.

What happens to unsupported modules and themes?

Starting 1 August 2023, any unsupported Drupal 7 module or theme will no longer be eligible for new maintenance once it goes unsupported. If a module or theme you rely on becomes unsupported, it’s crucial to proactively adopt or migrate it to a newer version. HeroDevs Drupal 7 NES also provides module support if you choose that route.

What are the PHP version requirements?

From 1 August 2023, Drupal 7 no longer supports PHP versions lower than 5.6. Further increases in the minimum PHP requirement may occur before Drupal 7's EOL.

Are there any specific operating system considerations?

Drupal 7 security fixes for Windows-only issues ceased on 1 August 2023. If your site runs on Windows, migrating to another operating system is recommended.

Will drupal.org continue to package Drupal 7 distributions?

No, as of 1 August  2023, Drupal.org stopped packaging Drupal 7 distributions. Users needing a distribution built must use Drush make locally.

What are my options moving forward?
  1. Migrate to Modern Drupal: Upgrading to Drupal 10 or the upcoming Drupal 11 is strongly recommended to ensure continued security, support, and access to new features. Modern Drupal versions adopt the latest PHP standards and offer enhanced performance and security. In addition, Drupal Starshot is coming at the end of 2024, which bundles Drupal core with cutting-edge features and easier maintenance.
  2. Extended Security Support: The Drupal Association has partnered with HeroDevs to offer Drupal 7 Never-Ending Support (NES). This service provides ongoing security updates, compliance support, and compatibility fixes for Drupal 7 sites, allowing businesses more time to transition.
  3. Stay on Unsupported Drupal 7: Continuing to use Drupal 7 after its EOL is an option but comes with significant risks, including increased vulnerability to security exploits and compliance issues. Over time, support for PHP versions and other dependencies will also wane, making it harder to maintain your site. Other vendors may join the program before end of life.
How can I find migration assistance?

The Drupal Association is certifying migration partners to help Drupal 7 site owners transition. Certified Migration Partners will be promoted on Drupal.org and can provide resources to assist in the migration process.

What should I do if I need help?

For assistance, consider engaging with the Drupal community or Certified Migration Partners. Donating to the Drupal Security Team or sponsoring core maintainers and contributors can also help ensure the continuity and security of Drupal projects.

Conclusion

Organizations must make informed decisions as Drupal 7's EOL approaches to maintain security, compliance, and functionality. Upgrading to Drupal 10, Drupal 11, or leveraging extended support options will position your site for long-term success.

Categories: FLOSS Project Planets

Qt Creator 14 released

Planet KDE - Thu, 2024-07-25 07:45

We are happy to announce the release of Qt Creator 14!

Categories: FLOSS Project Planets

Gary Benson: Python atomic counter

GNU Planet! - Thu, 2024-07-25 07:09

Do you need a thread-safe atomic counter in Python? Use itertools.count():

>>> from itertools import count >>> counter = count() >>> next(counter) 0 >>> next(counter) 1 >>> next(counter) 2

I found this in the decorator package, labelled Atomic get-and-increment provided by the GIL. So simple! So cool!

Categories: FLOSS Project Planets

The Drop Times: Drupal Cafe Lutsk #25 Recap: Key Insights and Community Support

Planet Drupal - Thu, 2024-07-25 05:39
Drupal Cafe Lutsk #25, held on June 27, 2024, featured sessions on Drupal's Domain module, digital opportunities for cities, and IT project optimization. Supported by Anyforsoft, YozmaTech, and DevBranch, the event highlighted valuable industry insights and community collaboration.
Categories: FLOSS Project Planets

Formatting Selected Text in QML

Planet KDE - Thu, 2024-07-25 04:00
Motivation

Let’s say we’re working on a QML project that involves a TextEdit.

There’s some text in it:

here is some text

We want to select part of this text and hit ctrl+B to make it bold:

here is some text

In Qt Widgets, this is trivial, but not so much in QML – we can get font.bold of the entire TextEdit, but not of just the text in the selection. We have to implement formattable selections manually.

To do this, there are two approaches we’ll look at:

  1. The first is to hack it together by getting the formatted text from the selection and editing this. Rather than setting properties of selected text, this solution actually inserts or removes formatting symbols from the underlying rich text source.
  2. The other way to do this is to create a QML object that is implemented in C++ and exposed to TextEdit as a property. This way we can make use of QTextDocument and QTextCursor to actually set text properties within the selection area. This more closely follows the patterns expected in Qt.

In Qt 6.7, the TextEdit QML element does have a cursorSelection property that works in this way, and by dissecting its implementation, we can write a pseudo-backport for other Qt versions.

Before we do this, let’s take a look at the hacky QML/JS solution.

Hacky Approach

We start by focusing on just making ctrl+B bold shortcuts work:

TextEdit { id: txtEdit anchors.fill: parent selectByMouse: true textFormat: TextEdit.RichText } Shortcut { sequence: StandardKey.Bold onActivated: { if (txtEdit.selectedText.length > 0) { const start = txtEdit.selectionStart const end = txtEdit.selectionEnd let sel = txtEdit.getFormattedText(start, end) .split("<!--StartFragment-->")[1] .split("<!--EndFragment-->")[0] txtEdit.remove(start, end) if (sel.includes("font-weight:600;")) sel = sel.replace("font-weight:600;", "") else sel = "<b>" + sel + "</b>" txtEdit.insert(txtEdit.cursorPosition, sel) txtEdit.select(start, end) } } }

Notice that we actually remove and replace the selected text, and reselect the insertion manually.

We can set up similar shortcuts for italics and underline trivially, but what if we want to set font properties of only the text in the selected area?

To keep things simple, let’s see what happens if we want to set just the font family and size:

FontDialog { id: fontDlg } Shortcut { id: fontShortcut property string sel: "" property int start: 0 property int end: 0 sequence: StandardKey.Find onActivated: { if (txtEdit.selectedText.length > 0) { start = txtEdit.selectionStart end = txtEdit.selectionEnd sel = txtEdit.getFormattedText(start, end) .split("<!--StartFragment-->")[1] .split("<!--EndFragment-->")[0] fontDlg.open() } } } Connections { target: fontDlg function onAccepted() { txtEdit.remove(fontShortcut.start, fontShortcut.end) if (fontShortcut.sel.includes("font-family:")) { let fontToReplace = fontShortcut.sel.split("font-family:'")[1].split("';")[0] fontShortcut.sel = fontShortcut.sel.replace(fontToReplace, fontDlg.font.family) } else { fontShortcut.sel = "<span style=\"font-family: '" + fontDlg.font.family + "'; font-size:" + (fontDlg.font.pixelSize ? fontDlg.font.pixelSize : fontDlg.font.pointSize) + "\">" + fontShortcut.sel + "</span>" } txtEdit.insert(txtEdit.cursorPosition, fontShortcut.sel) txtEdit.select(fontShortcut.start, fontShortcut.end) } }

If we start messing with other font style properties like italic, bold, spacing, etc., we will end up with almost unreadably nasty string manipulation here.

This solution is overall hacky, as we replace HTML-formatted text from a snipped out section. It would be more Qt-idiomatic to retrieve QFont info from a selection and set the properties without editing raw rich text. Furthermore, it’s better to do as much logic as possible in C++ rather than with JavaScript in QML.

Implementation of cursorSelection in Qt 6.7 QML

Let’s take a look at the cursorSelection property of QtQuick TextEdit in Qt 6.7.

By looking at its property declaration in qquicktextedit_p.h, the type of cursorSelection is QQuickTextSelection.

This type is very basic. It has four read/write properties.

Here is the header qquicktextselection_p.h:

class Q_QUICK_EXPORT QQuickTextSelection : public QObject { Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged FINAL) Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged FINAL) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL) Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged FINAL) QML_ANONYMOUS QML_ADDED_IN_VERSION(6, 7) public: explicit QQuickTextSelection(QObject *parent = nullptr); QString text() const; void setText(const QString &text); QFont font() const; void setFont(const QFont &font); QColor color() const; void setColor(QColor color); Qt::Alignment alignment() const; void setAlignment(Qt::Alignment align); Q_SIGNALS: void textChanged(); void fontChanged(); void colorChanged(); void alignmentChanged(); private: QTextCursor cursor() const; void updateFromCharFormat(const QTextCharFormat &fmt); void updateFromBlockFormat(); private: QTextCursor m_cursor; QTextCharFormat m_charFormat; QTextBlockFormat m_blockFormat; QQuickTextDocument *m_doc = nullptr; QQuickTextControl *m_control = nullptr; };

Notice we’ve got these private data members:

QTextCursor m_cursor; QTextCharFormat m_charFormat; QTextBlockFormat m_blockFormat; QQuickTextDocument *m_doc = nullptr; QQuickTextControl *m_control = nullptr;

The m_doc and m_control are retrieved from the TextEdit which parents the selection object. The object is always constructed by a QQuickTextEdit, so in the constructor, the parent is cast to one using qmlobject_cast. Then we set these two fields.

QQuickTextSelection::QQuickTextSelection(QObject *parent) : QObject(parent) { // When QQuickTextEdit creates its cursorSelection, it passes itself as the parent if (auto *textEdit = qmlobject_cast<QQuickTextEdit *>(parent)) { m_doc = textEdit->textDocument(); m_control = QQuickTextEditPrivate::get(textEdit)->control; // ... // ...

Now what are m_charFormat and m_blockFormat?

Text documents are composed of a list of text blocks, which can be paragraphs, lists, tables, images, etc. Thus, a block format represents an individual block’s alignment formatting. Char format contains formatting information at the character level, like font family, weight, style, size, color, and so forth.

To initialize these, we need to get the cursor from the text control.

QTextCursor QQuickTextSelection::cursor() const { if (m_control) return m_control->textCursor(); return m_cursor; }

The cursor will give us a char format and a block format, which we use to get the font / color / alignment at the cursor’s location.

QFont QQuickTextSelection::font() const { return cursor().charFormat().font(); } // ... QColor QQuickTextSelection::color() const { return cursor().charFormat().foreground().color(); } // ... Qt::Alignment QQuickTextSelection::alignment() const { return cursor().blockFormat().alignment(); }

currentCharFormatChanged is emitted by QQuickTextControl when the cursor moves or the document’s contents change. If this format is indeed different from the fields of the selection object, we must update them and emit the selection’s signals, just as we would in setters. Since we keep track of block alignment too, we have to do the same when the cursor moves and block format is different.

QQuickTextSelection::QQuickTextSelection(QObject *parent) : QObject(parent) { // When QQuickTextEdit creates its cursorSelection, it passes itself as the parent if (auto *textEdit = qmlobject_cast<QQuickTextEdit *>(parent)) { m_doc = textEdit->textDocument(); m_control = QQuickTextEditPrivate::get(textEdit)->control; connect(m_control, &QQuickTextControl::currentCharFormatChanged, this, &QQuickTextSelection::updateFromCharFormat); connect(m_control, &QQuickTextControl::cursorPositionChanged, this, &QQuickTextSelection::updateFromBlockFormat); } } // ... // ... // ... inline void QQuickTextSelection::updateFromCharFormat(const QTextCharFormat &fmt) { if (fmt.font() != m_charFormat.font()) emit fontChanged(); if (fmt.foreground().color() != m_charFormat.foreground().color()) emit colorChanged(); m_charFormat = fmt; } inline void QQuickTextSelection::updateFromBlockFormat() { QTextBlockFormat fmt = cursor().blockFormat(); if (fmt.alignment() != m_blockFormat.alignment()) emit alignmentChanged(); m_blockFormat = fmt; }

Here are the setters for the properties, which use the cursor to access and mutate the character or block properties at its position.

void QQuickTextSelection::setText(const QString &text) { auto cur = cursor(); if (cur.selectedText() == text) return; cur.insertText(text); emit textChanged(); } // ... void QQuickTextSelection::setFont(const QFont &font) { auto cur = cursor(); if (cur.selection().isEmpty()) cur.select(QTextCursor::WordUnderCursor); if (font == cur.charFormat().font()) return; QTextCharFormat fmt; fmt.setFont(font); cur.mergeCharFormat(fmt); emit fontChanged(); } // ... void QQuickTextSelection::setColor(QColor color) { auto cur = cursor(); if (cur.selection().isEmpty()) cur.select(QTextCursor::WordUnderCursor); if (color == cur.charFormat().foreground().color()) return; QTextCharFormat fmt; fmt.setForeground(color); cur.mergeCharFormat(fmt); emit colorChanged(); } // ... void QQuickTextSelection::setAlignment(Qt::Alignment align) { if (align == alignment()) return; QTextBlockFormat format; format.setAlignment(align); cursor().mergeBlockFormat(format); emit alignmentChanged(); }

Now, we want to do something like this in our code. The issue is that this implementation resides in the Qt source code itself, and cursorSelection is a property of QQuickTextEdit. If we want to do something like this without changing Qt source code, we have to use attached properties.

Implementing an Attached Property

Using CursorSelection as an attached property for a TextEdit in QML might look something like this:

Item { // ... // ... // ... Shortcut { // ctrl+B to toggle bold / not bold for selection sequence: StandardKey.Bold onActivated: { txtEdit.CursorSelection.font = Qt.font({ bold: txtEdit.CursorSelection.font.bold !== true }) } } TextEdit { id: txtEdit // ... CursorSelection.font { bold: false italic: false underline: false } } }

To create our own attached property, we have to create two classes: CursorSelectionAttached and CursorSelection.

CursorSelectionAttached will contain the implementation of the selection, while CursorSelection serves as the attaching type, using the qmlAttachedProperties() method to expose the signals and properties of an instance of CursorSelectionAttached to the parent to which it is attached.

CursorSelection also needs the QML_ATTACHED() macro in its header declaration, and we must specify that it has an attached property with the macro QML_DECLARE_TYPEINFO() outside the class scope.

Thus, CursorSelection will just look like this:

// CursorSelection.h class CursorSelection : public QObject { Q_OBJECT QML_ATTACHED(CursorSelectionAttached) QML_ELEMENT public: static CursorSelectionAttached *qmlAttachedProperties(QObject *object); }; QML_DECLARE_TYPEINFO(CursorSelection, QML_HAS_ATTACHED_PROPERTIES)

Where the entire implementation is just this function definition:

// CursorSelection.cpp CursorSelectionAttached *CursorSelection::qmlAttachedProperties(QObject *object) { if (auto *textEdit = qobject_cast<QQuickTextEdit *>(object)) return new CursorSelectionAttached(textEdit); return nullptr; }

Notice that we perform the qobject_cast here and forward the result as the parent of the attached object. This way we only construct an attached object if we can cast the parent object to a TextEdit.

Now, let’s see how CursorSelectionAttached should be implemented. We begin with the constructor:

// we know that parent will be a QQuickTextEdit * CursorSelectionAttached::CursorSelectionAttached(QQuickTextEdit *parent) noexcept : QObject(parent) , mEdit(parent) // this is the TextEdit we are attached to { // make sure the QTextDocument exists const auto *const quickDoc = mEdit->textDocument(); // QQuickTextDocument * auto *doc = quickDoc->textDocument(); // QTextDocument * Q_ASSERT(doc != nullptr); // retrieve QTextCursor from the QTextDocument mCursor = QTextCursor(doc); // When deselecting, the cursor position and anchor are // set to the TextEdit's cursor position connect(mEdit, &QQuickTextEdit::selectedTextChanged, this, &CursorSelectionAttached::moveAnchorIfDeselected); connect(mEdit, &QQuickTextEdit::cursorPositionChanged, this, &CursorSelectionAttached::updatePosition); // if we set a format with no selection, we keep it in an optional // then when new text is added, it will have this formatting // for example, with no selection we press ctrl+B and then start // typing. we expect the text to be bold. connect(mEdit->textDocument()->textDocument(), &QTextDocument::contentsChange, this, &CursorSelectionAttached::applyFormatToNewTextIfNeeded); }

Note that we connect to these three slots:

  • moveAnchorIfDeselected
  • updatePosition
  • applyFormatToNewTextIfNeeded

Let’s investigate the purpose of these.

moveAnchorIfDeselected is invoked when the TextEdit’s selected text changes. A QTextCursor has an anchor, which controls selection area. If text is being selected, the anchor is fixed in place where the selection is started, and the cursor position moves independently of the anchor. The selection area is located between the two positions. When a cursor moves without selecting anything, the anchor is located at and moves along with the cursor position.

Thus, when a cursor’s position is moved, we need to know if the anchor should be moved with it.

Since we invoke moveAnchorIfDeselected when the selected text changes, we know that if the selection is now empty, this means there was a selection that has been deselected. Thus, the cursor and anchor should be equal to one another.

void CursorSelectionAttached::moveAnchorIfDeselected() { if (mEdit->selectedText().isEmpty()) mCursor.setPosition(mEdit->cursorPosition(), QTextCursor::MoveAnchor); }

updatePosition is invoked when the TextEdit’s cursor position changes. Depending on the TextEdit’s selection start and end positions, there are a few ways the cursor could be updated.

If there is no selected area in the TextEdit, the cursor and anchor should move together. If a selection’s start and end position both change, we must move the cursor twice: once to the start position, with the anchor moving, and once to the end position, with the anchor fixed in place. If the selection area is being resized, for example by dragging or using Shift+ArrowKeys, the cursor should move with the anchor fixed in place.

void CursorSelectionAttached::updatePosition() { // if there's no selection, just move the cursor & anchor if (mEdit->selectionEnd() == mEdit->selectionStart()) { mCursor.setPosition(mEdit->cursorPosition(), QTextCursor::MoveAnchor); } // if both the start and end need to be updated: // move cursor and anchor to selection start, and // move cursor to selection end while keeping anchor at start // // we have to make sure the anchor is moved correctly so the // whole selection matches up -- otherwise cursor selection // start or end might be in the middle of the actual // selection, wherever the anchor is else if (mEdit->selectionStart() != mCursor.selectionStart() && mEdit->selectionEnd() != mCursor.selectionEnd()) { mCursor.setPosition(mEdit->selectionStart(), QTextCursor::MoveAnchor); mCursor.setPosition(mEdit->selectionEnd(), QTextCursor::KeepAnchor); } // these two cases are for selection dragging, only start or // end will move, so anchor stays in place else if (mEdit->selectionStart() != mCursor.selectionStart()) { mCursor.setPosition(mEdit->selectionStart(), QTextCursor::KeepAnchor); } else if (mEdit->selectionEnd() != mCursor.selectionEnd()) { mCursor.setPosition(mEdit->selectionEnd(), QTextCursor::KeepAnchor); } }

applyFormatToNewTextIfNeeded is invoked when the contents of the text document change. This is because font properties might be set without an active selection. In this case, the expected behavior is for the characters added afterwards will have these properties.

For example, if the font family is changed with no selection, and we start typing, we expect our text to be in this new font. To do this, we need an optional in which we can save a format to apply to new text if needed, or otherwise contains nullopt. We will call it mOptFormat. It can be set in property setters, which you will see later. For now, we just make sure to use it when the text document content changes and there exists a value in the optional.

void CursorSelectionAttached::applyFormatToNewTextIfNeeded(int from, int charsRemoved, int charsAdded) { if (charsAdded && mOptFormat) { mCursor.setPosition(mCursor.position() - 1, QTextCursor::KeepAnchor); mCursor.mergeCharFormat(mOptFormat.value()); mOptFormat.reset(); } }

Now, let’s take a look at the properties to expose to QML, and how they can be retrieved and set using the cursor. Like the QQuickTextSelection implementation, we will have properties text and font. We can implement the others as well, but for the sake of brevity, we will just focus on these two.

Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged FINAL) Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged FINAL)

We’ll need to declare and define these getters and setters, and declare the signals:

Getters:

[[nodiscard]] QString text() const; [[nodiscard]] QFont font() const;

Setters:

void setText(const QString &text); void setFont(const QFont &font);

Signals:

void textChanged(); void fontChanged();

The getter and setter implementations will look very similar to the previous implementations shown for QQuickTextSelection, with some minor differences.

Getter implementations:

QString CursorSelectionAttached::text() const { return mCursor.selectedText(); } QFont CursorSelectionAttached::font() const { // simply get the font at the cursor position using charFormat auto ret = mCursor.charFormat().font(); // if the cursor is at the start of a selection, we need to take the font // at the position right in front of it. otherwise, the font will refer to the // character at the position right before the selection begins if (mCursor.hasSelection() && mCursor.position() == mCursor.selectionStart()) { auto cur = mCursor; cur.setPosition(cur.position() + 1); ret = cur.charFormat().font(); } return ret; }

Setter implementations:

void CursorSelectionAttached::setText(const QString &text) { if (mCursor.selectedText() == text) return; mCursor.insertText(text); emit textChanged(); } void CursorSelectionAttached::setFont(const QFont &font) { if (font == mCursor.charFormat().font()) return; QTextCharFormat fmt = mCursor.charFormat(); fmt.setFont(font, QTextCharFormat::FontPropertiesSpecifiedOnly); // when no selection, formatting must be set on the next insertion if (mCursor.selection().isEmpty()) mOptFormat = fmt; else mCursor.mergeCharFormat(fmt); emit fontChanged(); }

The only thing that needs to be done now is override the destructor, which can just be set to default:

~CursorSelectionAttached() override = default;

Now we have all the implementation we need to use the attached property. If we put the two classes in one header file, it will look like this:

#pragma once #include <QObject> #include <QTextCursor> #include <QtQml> #include <optional> class QQuickTextEdit; class CursorSelectionAttached : public QObject { Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged FINAL) Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged FINAL) QML_ANONYMOUS public: explicit CursorSelectionAttached(QQuickTextEdit *parent) noexcept; ~CursorSelectionAttached() override = default; [[nodiscard]] QString text() const; [[nodiscard]] QFont font() const; void setText(const QString &text); void setFont(const QFont &font); signals: void textChanged(); void fontChanged(); private slots: void moveAnchorIfDeselected(); void updatePosition(); void applyFormatToNewTextIfNeeded(int from, int charsRemoved, int charsAdded); private: QTextCursor mCursor; QQuickTextEdit *mEdit; std::optional<QTextCharFormat> mOptFormat; }; class CursorSelection : public QObject { Q_OBJECT QML_ATTACHED(CursorSelectionAttached) QML_ELEMENT public: static CursorSelectionAttached *qmlAttachedProperties(QObject *object); }; QML_DECLARE_TYPEINFO(CursorSelection, QML_HAS_ATTACHED_PROPERTIES)

With this header, an implementation file containing the definitions, and a call to qmlRegisterUncreatableType<CursorSelection> in your main.cpp, the attached property can be used in QML.

Final Remarks

Though this is not a perfect backport, this code allows us to set font properties for selected text in QML in a nearly identical way to its implementation in Qt 6.7. This is especially useful to implement any kind of richtext editing in a QML application, where this functionality is severely lacking in any Qt version prior to 6.7. Hopefully this is a helpful guide to backporting features, implementing attached properties, and doing more sane text editing in QML apps.

About KDAB

If you like this article and want to read similar material, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

The post Formatting Selected Text in QML appeared first on KDAB.

Categories: FLOSS Project Planets

EuroPython Society: EuroPython 2024 Code of Conduct Transparency Report

Planet Python - Thu, 2024-07-25 02:00

The 2024 version of the EuroPython conference took place both online and in person in July 2024. This was the second conference under our new Code of Conduct (CoC), and we had Code of Conduct working group members continuously available both online and in person.

Reports

We had 4 Code of Conduct working group members continuously available both online and in person. Over the course of the conference the Code of Conduct team was made aware of the following issues:

  • A disabled person had requested reserved seating for talks, but when he arrived the first day, there was none. He reported this to a CoC member, who filed a report with Ops. It turned out that while the request had been gathered on the web form, there was no mechanism to get that information to the people involved. Once they were informed, the issue was quickly resolved, and the reporter expressed satisfaction with the way it was handled.
  • One person was uncomfortable with having their last name shown on Discord. They were informed that they could change that as soon as the registration bot ran, limiting the exposure to a minute or so, or that they could come to the registration desk for assistance. The report came via email and there was no response to the email suggesting those options.
  • An attendee reported that one talk&aposs slides included a meme that seemed to reflect a racist trope. The CoC team reviewed that talk&aposs slides, and agreed that the meme might be interpreted that way. A member of the CoC team contacted the presenter who immediately agreed to remove that meme before uploading the slides, and the video team was alerted to edit that meme out of the talk video before final publication.
  • There were multiple reports that the toilet signage was confusing and causing people to be uncomfortable with choosing a toilet. Once this was reported the signage was adjusted to make the gender designation visible and no further reports were received. It should be noted that none of the complaints objected to the text of the signs, just to the fact that covering of gender markers led to people entering a toilet they didn&apost want to.
  • The CoC team also were presented with a potential lightning talk topic that had caused complaints at another conference due to references to current wars that some viewers found disturbing. Since lightning talks are too short for content warnings to be effective, and since they are not reviewed in any detail by the programme committee, the CoC team counselled the prospective presenter against using the references that had been problematic at a prior conference. Given that advice, the presenter elected not to submit that topic.
Categories: FLOSS Project Planets

Pages