FLOSS Project Planets

Kdenlive 22.04.2 Released

Planet KDE - Tue, 2022-06-14 11:02

The polishing and stability effort of this release cycle continues with the release Kdenlive 22.04.2 which comes with bug fixes to the AppImage and Mac packages, render widget, same track transitions, subtitles and project loading issues.

 

  • Fix icon color change in some situations (eg. Appimage). Commit. Fixes bug #450556
  • Fix incorrect lambda capture leading to crash. Commit.
  • Fix AppImage icons. Commit. See bug #451406
  • Online resources: only show warning about loading time once. Commit. See bug #454470
  • Clang format fixes. Commit.
  • Fix crash clicking ok in empty transcoding dialog. Commit.
  • Fix possible crash when load task is running on exit. Commit.
  • Fix file watcher broken, changed clips were not detected anymore. Commit.
  • Fix timeremap clip always using proxies on rendering. Commit. Fixes bug #454089
  • Ensure internal effects like subtitles stay on top so that they are not affected by color or transform effects. Commit.
  • Fix crash on undo center keyframe. Commit.
  • Fix crash changing clip monitor bg color when no clip is selected. Commit.
  • Fix crash on undo selected clip insert. Commit.
  • Fix nvenc codec. Commit. See bug #454469
  • Fix clip thumbs not discarded on property change. Commit.
  • On document loading, also check images for changes. Commit.
  • Fix tests and mix direction regression. Commit.
  • Fix major corruption on undo/redo clip cut, with tests. Commit.
  • Project loading: detect and fix corruption if audio or video clips on the same track use a different producer. Commit.
  • Fix crash dropping an effect on the clip monitor. Commit.
  • Speedup maker search. Commit.
  • Fix cannot put monitor in fullscreen with mirrored screens. Commit.
  • Fix mix on very short AV clips broken, with test. Commit.
  • Fix Slide mix not correctly updated when creating a new mix on the previous clip, add tests. Commit. See bug #453770
  • Fix mix mix not correctly reversed in some cases and on undo. Commit.
  • Fix slide composition going in wrong direction (mix is still todo). Commit. See bug #453770
  • Fix several small glitches in bin selection. Commit.
  • Fix clip height not aligned to its track. Commit.
  • Fix speech to text on Mac. Commit.
  • Fix crash/corruption in overwrite mode when moving grouped clips above or below existing tracks. Commit.
  • Fix missing audio with “WebM-VP9/Opus (libre)” preset. Commit. See bug #452950
  • [Render Widget] Allow more steps for quality slider. Commit.
  • [Render Presets] Fix wrongly reversed quality with custom presets. Commit.
  • [Render Presets] Add more speed preset steps for x254 and x256. Commit.
  • Fix mixers don’t display levels if a track was added/removed with collapsed mixer. Commit.
  • Fix possible crash in transcoding dialog if there are no clips to convert. Commit.
  • [RenderWidget] Add scrollbar to improve experience on small screens. Commit.

The post Kdenlive 22.04.2 Released appeared first on Kdenlive.

Categories: FLOSS Project Planets

Mike Driscoll: Data Science Packages in Python (Video)

Planet Python - Tue, 2022-06-14 10:46

In this tutorial, I will talk about some of the many different data science packages you can use in Python.

Packages mentioned: pandas, matplotlib, numpy, scipy, mahotas, OpenCV, Keras, PyTorch, Tensorflow, Theano, Bokeh, Plotly, Scikit-learn, Scikit-image

The post Data Science Packages in Python (Video) appeared first on Mouse Vs Python.

Categories: FLOSS Project Planets

PyBites: How to make a nice graph using Django and Chart.js

Planet Python - Tue, 2022-06-14 10:41

In this article I will show you how to make a beautiful yet simple graph using Django + Chart.js. 

The code for this project is here.

Getting the data

We are going to plot the number of Bite exercises that get completed per month on our platform

For this I exported the live data from the corresponding table in our database using this handy Postgres command:

postgres@0:pybites> \copy (select * from bites_table) to '~/Downloads/bites.csv' WITH (FORMAT CSV, HEADER)

This will export the content of the table to a csv file.

Setting up Django

Next we will make a Django project and app so we can share it with this post:

$ mkdir bite_stats && cd $_ √ bite_stats $ python3.10 -m venv venv && source venv/bin/activate (venv) √ bite_stats $ pip install django python-dateutil # latter for date parsing ... (venv) √ bite_stats $ django-admin startproject mysite . (venv) √ bite_stats $ django-admin startapp stats (venv) √ bite_stats $ tree . ├── manage.py ├── mysite │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── stats ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py └── views.py 3 directories, 13 files

Note the trailing dot (.) to the startproject command. I always do that in Django to not get the extra nested directory.

Create a model (database table)

Next let’s make the model that will hold the stats for our graph. I keep it very simple because the purpose of this post is to make a simple graph:

from django.db import models class BiteStat(models.Model): exercise = models.PositiveSmallIntegerField() # 0 to 32767 completed = models.DateField() # I don't care about time here level = models.PositiveSmallIntegerField(null=True, blank=True) # optional, not every Bite has user feedback

I add the stats app to my INSTALLED_APPS in settings.py and run python manage.py makemigrations to make the migration file, then python manage.py migrate to sync it (and all other pending Django migrations) to the database.

Note we just use the standard sqlite3 database that Django provides out of the box.

Also note I did not update the secret key and other env variables, because this is a toy app example. Check this video how to do this in a regular Django project.

Django importer command

Next let’s get the stats csv loaded in using a Django command.

First make the required directory structure:

(venv) √ bite_stats $ mkdir -p stats/management/commands

Then make a module in that directory. The name you’ll give it will become the new switch to manage.py, I am going with stats/management/commands/import_stats.py so I can run it like: python manage.py import_stats

As per the docs we need to subclass BaseCommand and implement the handle() method.

I actually did a complete walk through of Django commands here.

I am adding a command line argument -c (--csv) to point the csv file on my computer. 

Note that I parse the date string to a datetime object using python-dateutil and I need to convert rows without a user level to 0 to stay consistent with the column type:

import csv from django.core.management.base import BaseCommand from dateutil.parser import parse from stats.models import BiteStat class Command(BaseCommand): help = 'Import bite exercise stats' def add_arguments(self, parser): parser.add_argument('-c', '--csv', required=True) def handle(self, *args, **options): file = options["csv"] with open(file) as f: reader = csv.DictReader(f) for row in reader: completed = row["first_completed"] if not completed: continue level = row["user_level"] if not level: level = 0 date = parse(completed) stat, created = BiteStat.objects.get_or_create( exercise=row["bite_id"], completed=date, level=level, ) if created: self.stdout.write(f"{stat} created") else: self.stderr.write(f"{stat} already in db")

Some more observations:

  • We get the command line arg through the options dict.
  • csv.DictReader() is really nice to load in a csv file and associate each row with the column names (keys).
  • Django ORM’s get_or_create() is a nice helper to only create the object if it does not exist yet. This makes the script idempotent (I can run it again without getting duplicate records).
  • We use the super class’ stdout and stderr objects for nicer output formatting.

Let’s run it:

python manage.py import_stats -c ~/Downloads/bites.csv

This is literally scrolling over the terminal for a good while as I am writing this, lot of Bites completed on our platform

Let’s now plot this data in a simple view using Chart.js …

Create a route to a new view

I am creating a view and route first:

from django.contrib import admin from django.urls import path from stats import views urlpatterns = [ path('', views.index), # new path('admin/', admin.site.urls), ]

To keep it simple I just do this in the main router (urls.py), not making a new one at the app level.

Create a view to get the data and link to a template

In stats/views.py I create a simple (function based) view to retrieve the records we just imported and build up the x and y values for the graph.

Btw I much prefer function based views over class based ones, see this resource why …

from collections import Counter from math import ceil from django.shortcuts import render from stats.models import BiteStat def index(request): stats = BiteStat.objects.order_by('completed') data = Counter() for row in stats: yymm = row.completed.strftime("%Y-%m") data[yymm] += 1 # unpack dict keys / values into two lists labels, values = zip(*data.items()) context = { "labels": labels, "values": values, } return render(request, "graph.html", context)

For counting things collections.Counter() is a Standard Library staple and zip(*list_of_tuples) is a nice way to unpack values to a list of labels + values.

Create the template with the graph using Chart.js

I render a graph.html template we’ll create next. I put this template in mysite/templates, a directory I created.

I took the basic example from the docs page, linked to the library using its CDN, and used Django’s templating language to populate the labels and data attributes as per the (context) variables passed in from the view.

Note that normally we would abstract repeated template code in a base.html and use inheritance. I just used a single template to keep things simple.

<!DOCTYPE html> <html> <head> <title>Bite exercise stats</title> </head> <body> <canvas id="myChart" width="800" height="400"></canvas> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> const ctx = document.getElementById('myChart').getContext('2d'); const myChart = new Chart(ctx, { type: 'bar', data: { labels : [{% for item in labels %}"{{ item }}",{% endfor %}], datasets: [{ label: "Bite exercises complete per month", data : [{% for item in values %}{{ item }},{% endfor %}], backgroundColor: 'rgba(75, 192, 192, 0.2)', borderColor: 'rgba(75, 192, 192, 1)', borderWidth: 1 }] }, options: { scales: { y: { beginAtZero: true } } } }); </script> </body> </html>

In order for Django to find this template I put the path to the template directory to DIRS in the TEMPLATES list in settings.py:

TEMPLATES = [ ... 'DIRS': [Path(BASE_DIR) / 'mysite' / 'templates'], ...

Again check out the source code of this project in this repo.

The resulting graph

Now let’s run python manage.py runserver and see if it works …

Navigating to localhost:8000 I see this – sweet!

Bite exercises completed per month since we started with the platform. Hovering over the bars with your mouse you get nice tooltips. Wrap up

Cool! There are two peaks, what were those? It turns out those were the two months we participated in some massive Humble Bundle promotions where we offered Bite exercise packages.

A lot of people signed up to the platform then and started to redeem their Bite tokens and hence code the Bites. It’s really cool to see those trends using data visualization.

Overall we’re blown away with a steady rate of > 1K exercises being solved every month!

So there you go, I hope this gave you a little template you can use to easily build your own graph using Django.

We challenge you!

Note that I also imported the user_level (scale 1-10) per Bite. What if you create a second graph to show the Bites on the x-axis and their average user_level (difficulty) ratings on the y-axis?

Remember deliberate practice is key, so it’s time to fork the repo and get your hands dirty

Feel free to PR (pull request) your solution …

Good luck and keep calm and code in Python!

– Bob

Categories: FLOSS Project Planets

Real Python: Combining Data in pandas With concat() and merge()

Planet Python - Tue, 2022-06-14 10:00

The Series and DataFrame objects in pandas are powerful tools for exploring and analyzing data. Part of their power comes from a multifaceted approach to combining separate datasets. With pandas, you can merge and concatenate your datasets, allowing you to unify and better understand your data as you analyze it.

In this video course, you’ll learn how and when to combine your data in pandas with:

  • merge() for combining data on common columns or indices
  • concat() for combining DataFrames across rows or columns

If you have some experience using DataFrame and Series objects in pandas and you’re ready to learn how to combine them, then this video course will help you do exactly that. If you’re feeling a bit rusty, then you can watch a quick refresher on DataFrames before proceeding.

[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

Categories: FLOSS Project Planets

Plasma 5.25: Amazement Guaranteed

Planet KDE - Tue, 2022-06-14 07:45

Plasma 5.25 brings new features and concepts to the desktop environment. Check out how you can now handle your desktop through gestures on your touchpad or touchscreen, the advanced and easy to use customization features, an improved and very useful Overview, and much, much more.

Find out more about this release

Music: Lightness By Nomyn, distributed under a CC By license.

Special thanks to: Maksym Hazevych, Ryhor Aŭrukievič, Manuel Jesús de la Fuente, Freya, Aditya Yadav, Rachit, David McCullah, Aura Herrero Ruiz

Categories: FLOSS Project Planets

The Drop Times: 10 Best E-commerce Modules For Drupal 9 [Most Installed]

Planet Drupal - Tue, 2022-06-14 06:57
Drupal e-commerce modules are useful for managing various aspects of your site, that's why you should know which modules are worth getting. Here are the most installed e-commerce modules.
Categories: FLOSS Project Planets

PyCharm

Planet Python - Tue, 2022-06-14 06:39

I’ve been a long-time Pandas user, relying on it heavily since the start of my data science career. However, up until the last couple of years, I struggled with certain issues, such as not being able to work with very large DataFrames or efficiently run heavy data processing tasks. I’d also often find my Jupyter notebooks cluttered with intermediate DataFrames after applying transformations, making it harder to read the code and keep my notebook tidy. For a long time, I had thought that these issues were just endemic to Pandas and accepted there wasn’t a better way; however, there is!

If you find yourself dealing with similar issues, join Matt and me as we discuss tips for making Pandas more memory-friendly, getting the best performance possible when applying operations to Series and DataFrames, and keeping your Pandas code as reproducible and tidy as possible. We’ll also be talking about using Pandas as a powerful basis for data visualization, and how using the right tooling can make working with Pandas easier.

Attendees of this webinar will receive a discount code for Matt’s book, Effective Pandas, which includes even more tips on how to get the most out of Pandas. In addition, join us on Twitter where we’re running a competition this week asking for your best Pandas tips. Five tips will be selected during the webinar and the winners will receive a free hard copy of the book!

When
  • Tuesday, June 21
  • 5:00 pm (UTC)

Register Now!

Speaking to You

Matt Harrison runs MetaSnake, a Python and Data Science consultancy and corporate training shop. In the past, he has worked across the domains of search, build management and testing, business intelligence, and storage. He has presented and taught tutorials at conferences such as Strata, SciPy, SCALE, PyCON, and OSCON, as well as local user conferences. He has written a number of books on Python and Data Science, including Machine Learning Pocket Reference, Pandas 1.x Cookbook, Effective PyCharm, and Effective Pandas. He blogs at hairysun.com.

Dr. Jodie Burchell is a Developer Advocate for Data Science at JetBrains and was previously the Lead Data Scientist in audiences generation at Verve Group Europe. After finishing a PhD in psychology and a postdoc in biostatistics, she has worked in a range of data science and machine learning roles across search improvement, recommendation systems, natural language processing, and programmatic advertising. She is also the author of two books, The Hitchhiker’s Guide to Ggplot2 and The Hitchhiker’s Guide to Plotnine, and blogs at t-redactyl.io.

Categories: FLOSS Project Planets

ListenData: Region Proposal Network (RPN) : A Complete Guide

Planet Python - Tue, 2022-06-14 06:14
This tutorial includes detailed step by step guide of how Region Proposal Network (RPN) works. It is mainly used in RCNN family for object detection. Those who are familiar with RCNN, they might already have encountered the term Region Proposal Network. Before we get into details of RPN, let's understand how object detection works using R-CNN. Object Detection using R-CNN

R-CNN is a Region based Convolutional Neural Network. It is a state of art architecture for object detection. Let's say you have a photograph, the goal of objective detection is to detect cars and people in the photograph. There are a couple of cars and people in the photograph so we need to detect all of them.

How does it work? 1. Region Proposal

Extract many regions from an image using Selective Search. 2000 regions were used in the original whitepaper. Regions are drawing multiple bounding boxes in the input image. See the yellow bordered boxes in the image below.

2. Calculate CNN Features

Create feature vector for each region proposed using CNN network trained for classifying image

3. Classify Regions

Classify each region using linear Support Vector Machine model for each category by passing feature vector generated in the previous step.

Region Proposal Network : What does it do?

In R-CNN we have learnt extracting many regions using Selective Search. The problem with the Selective Search is that it's an offline algorithm and computationally expensive. Here Region proposal network comes into picture. In Faster R-CNN, Region Proposal Network were introduced to use a small network to predict region proposals. RPN has classifier that returns the probability of the region. It also has regressor that returns the coordinates of the bounding boxes.

Following are the steps involved in Region Proposal Network

READ MORE »
Categories: FLOSS Project Planets

Andre Roberge: Friendly IDLE

Planet Python - Tue, 2022-06-14 04:10

friendly_idle is now available.  This is just a quick announcement. Eventually I plan to write a longer blog post explaining how I use import hooks to patch IDLE and to provide seamless support for friend/friendly_traceback.  Before I incorporated "partial" support for IDLE within friendly, I had released a package named friendly_idle ... but this is really a much better version.


When you launch it from a terminal, the only clue you get that this is not your regular IDLE is from the window title.


Since Python 3.10 (and backported to Python 3.8.10 and 3.9.5), IDLE provide support for sys.excepthook() (see announcement).  Actually, in the announcement, it is not pointed out that this is only partial support: exceptions raised because of syntax errors cannot be captured by user-defined exception hooks.  However, fear not, friendly_idle is perfectly capable to help you when your code has some syntax errors.


And, of course, it can also do so for runtime errors.

The same is true for code run from a file as well:


If the code in a file contains some syntax error, friendly_idle is often much more helpful than IDLE. Here's an example from IDLE:And the same example run using friendly_idle
Unfortunately, the tkinter errorbox does not use a monospace font (assumed by friendly/friendly_traceback for the formatting), and does not allow customization.  I might have to figure out how to create my own dialog, hopefully with support for monospace font and colour highlighting. If anyone has some experience doing this, feel free to contact me! ;-)






Categories: FLOSS Project Planets

Python Bytes: #288 Performance benchmarks for Python 3.11 are amazing

Planet Python - Tue, 2022-06-14 04:00
<p><strong>Watch the live stream:</strong></p> <a href='https://www.youtube.com/watch?v=2ZTEEy1_Gkk' style='font-weight: bold;'>Watch on YouTube</a><br> <br> <p><strong>About the show</strong></p> <p>Sponsored by us! Support our work through:</p> <ul> <li>Our <a href="https://training.talkpython.fm/"><strong>courses at Talk Python Training</strong></a></li> <li><a href="https://testandcode.com/"><strong>Test &amp; Code</strong></a> Podcast</li> <li><a href="https://www.patreon.com/pythonbytes"><strong>Patreon Supporters</strong></a></li> </ul> <p><strong>Brian #1:</strong> <a href="https://www.pola.rs/"><strong>Polars: Lightning-fast DataFrame library for Rust and Python</strong></a></p> <ul> <li>Suggested by a several listeners</li> <li>“Polars is a blazingly fast DataFrames library implemented in Rust using <a href="https://arrow.apache.org/docs/format/Columnar.html">Apache Arrow Columnar Format</a> as memory model. <ul> <li>Lazy | eager execution</li> <li>Multi-threaded</li> <li>SIMD (Single Instruction/Multiple Data)</li> <li>Query optimization</li> <li>Powerful expression API</li> <li>Rust | Python | ...”</li> </ul></li> <li>Python API syntax set up to allow parallel and execution while sidestepping GIL issues, for both lazy and eager use cases. From the docs: <a href="https://pola-rs.github.io/polars-book/user-guide/dsl/groupby.html#do-not-kill-the-parallelization">Do not kill parallelization</a></li> <li><p>The syntax is very functional and pipeline-esque:</p> <pre><code>import polars as pl q = ( pl.scan_csv("iris.csv") .filter(pl.col("sepal_length") &gt; 5) .groupby("species") .agg(pl.all().sum()) ) df = q.collect() </code></pre></li> <li><p><a href="https://pola-rs.github.io/polars-book/user-guide/">Polars User Guide</a> is excellent and looks like it’s entirely written with Python examples.</p></li> <li>Includes <a href="https://pola-rs.github.io/polars-book/user-guide/dsl/video_intro.html">a 30 min intro video from PyData Global 2021</a></li> </ul> <p><strong>Michael #2:</strong> <a href="https://lp.jetbrains.com/python-developers-survey-2021/"><strong>PSF Survey is out</strong></a></p> <ul> <li>Have a look, their page summarizes it better than my bullet points will.</li> </ul> <p><strong>Brian #3:</strong> <a href="https://github.com/google/gin-config"><strong>Gin Config: a lightweight configuration framework for Python</strong></a></p> <ul> <li>Found through Vincent D. Warmerdam’s excellent <a href="https://calmcode.io/gin/intro-to-gin.html">intro videos on gin on calmcode.io</a></li> <li>Quickly make parts of your code configurable through a configuration file with the <code>@gin.configurable</code> decorator.</li> <li><p>It’s in interesting take on config files. (Example from Vincent)</p> <pre><code> # simulate.py @gin.configurable def simulate(n_samples): ... # config.py simulate.n_samples = 100 </code></pre></li> <li><p>You can specify:</p> <ul> <li>required settings: <code>def</code> <code>simulate</code>(n_samples=gin.REQUIRED)`</li> <li>blacklisted settings: <code>@gin.configurable(blacklist=["n_samples"])</code></li> <li>external configurations (specify values to functions your code is calling)</li> <li>can also references to other functions: <code>dnn.activation_fn = @tf.nn.tanh</code></li> </ul></li> <li>Documentation suggests that it is especially useful for machine learning.</li> <li>From motivation section: <ul> <li>“Modern ML experiments require configuring a dizzying array of hyperparameters, ranging from small details like learning rates or thresholds all the way to parameters affecting the model architecture.</li> <li>Many choices for representing such configuration (proto buffers, tf.HParams, ParameterContainer, ConfigDict) require that model and experiment parameters are duplicated: at least once in the code where they are defined and used, and again when declaring the set of configurable hyperparameters.</li> <li>Gin provides a lightweight dependency injection driven approach to configuring experiments in a reliable and transparent fashion. It allows functions or classes to be annotated as <code>@gin.configurable</code>, which enables setting their parameters via a simple config file using a clear and powerful syntax. This approach reduces configuration maintenance, while making experiment configuration transparent and easily repeatable.”</li> </ul></li> </ul> <p><strong>Michael #4:</strong> <a href="https://twitter.com/EduardoOrochena/status/1534913062356099079"><strong>Performance benchmarks for Python 3.11 are amazing</strong></a></p> <ul> <li>via Eduardo Orochena</li> <li>Performance may be the biggest feature of all</li> <li>Python 3.11 has <ul> <li>task groups in asyncio</li> <li>fine-grained error locations in tracebacks</li> <li>the self-type to return an instance of their class</li> </ul></li> <li>The "Faster CPython Project" to speed-up the reference implementation. <ul> <li>See my interview with Guido and Mark: <a href="https://talkpython.fm/339"><strong>talkpython.fm/339</strong></a></li> <li>Python 3.11 is 10~60% faster than Python 3.10 according to the official figures</li> <li>And a 1.22x speed-up with their standard benchmark suite.</li> </ul></li> <li>Arriving as stable until October</li> </ul> <p><strong>Extras</strong> </p> <p>Michael:</p> <ul> <li><a href="https://www.python.org/downloads/release/python-3105/"><strong>Python 3.10.5 is available</strong></a> (<a href="https://docs.python.org/release/3.10.5/whatsnew/changelog.html#python-3-10-5-final">changelog</a>)</li> <li><a href="https://www.raycast.com"><strong>Raycast</strong></a> (vs Spotlight) <ul> <li>e.g. CMD+Space =&gt; pypi search: <img src="https://paper-attachments.dropbox.com/s_89E5FC1F5DBBED983E2558E0DE9902BF8E7733F0236C1030506F258E61A5C2AF_1655219401413_pypisearch.png" alt="" /></li> </ul></li> </ul> <p><strong>Joke:</strong> <a href="https://devhumor.com/media/why-wouldn-t-you-choose-a-parrot-for-your-next-application"><strong>Why wouldn't you choose a parrot for your next application</strong></a></p>
Categories: FLOSS Project Planets

Kalendar Contact Book - Current Progress

Planet KDE - Tue, 2022-06-14 03:00

During my long train trip to the Linux App Summit 2022, I started working on a contact book feature in Kalendar. There was already a small contact integration in the event editor to select attendees for an event and I wanted to extend it with a simple contact info viewer and editor.

When I started it, I was full of hope that this would be a simple task and would be easy to finish. Unfortunately more than one month later, it’s not finished but there is a lot of progress that I can already show off.

The Contact View

The contact view is the most immediate visual change that users will notice when starting Kalendar. It’s a new view available in the sidebar and it will display all your contacts synchornized with Kalendar. It’s also feature a search field, to easily find a contact very helpful when you have many hundreds contats.

The contact view showing a few contacts

Currently not all the properties that an vcard can contains are displayed, but it is easy to add more of them later on.

Internally, the contact view uses an Akonadi::ItemMonitor so that the changes to the contact are immediately reflected in the view, even if the changes happened in KAddressBook or were synced in the background from an online service.

Contact Book Settings

Kalendar has access to the same sources as KAddressBook with for example WebDav (e.g. Nextcloud), Etesync, Microsoft Exchange Server and local vCard files.

The Google contact provider is still broken due to a massive API change in Google API. It’s a good reminder that open standards are better for the users and the developers sanity.

Contact book source settings

QR Code Sharing

From the contact view, it is also possible generate a QR code. This makes it easy to share one contact to your phone. If you want to shares and synchronize multiples contacts, it’s better to use a CardDav-based solution like Nextcloud.

QR code sharing

Plasma Applet

After implementing the contact view, with Claudio we decided to try to keep the codebase for the calendar and contact support mostly seperated from each others. To to so we created a QML plugin that contains all the contact utility and that can simply be imported with import org.kde.kalendar.contact 1.0.

This code seperation helped us develop a Plasma applet integrated inside the system try for the contact book.

The applet provides an easy way to search for a contact and send them an email or start a call using KDE Connect.

Searching in the Plasma applet

An contact book Plasma applet

It’s also possible to share with a QR code directly from the Plasma applet.

Contact Editor

The contact editor turned out more complicated than planned and is still missing a lot of features.

The contact editor

Currently, it only allows to edit the name, the phone numbers and emails of a contact. When editing the name you also have the choice to set each components of the name separately.

Advanced name options

There is also handling for the case there the contact was edited in another Akonadi-powered editor (like KAddressBook), asking the user what to do when detecting multiple concurrent editing of the same contact.

Change detection

Contact Group

Kalendar also has support for contact groups. This allows to create a group of contacts with an associated email address. It’s quite helpful when you want to often send mails to a group of contact.

Contact Group

You can also edit them, add more contacts and concurrent editing detection is also built-in the contact group editor.

Contact Group editing

Future

There is still a lot of features missings left to implement. For example, contact deletion, moving/copying a contact to another contact book but also a lot of contact properties need to be implemented in the contact book.

These features are relatively straigh forward to implement now that the base is here and if you want to help with the implementation, join our Matrix room. We would be happy to guide you.

Hopefully this will all be ready before the 22.08 release.

The Kalendar team is also working on another big component for Kalendar, stay tunned.

Categories: FLOSS Project Planets

GSoC Post 0: Introduction

Planet KDE - Tue, 2022-06-14 00:08

Hello, reader! I am Suhaas Joshi, a 20-year-old 3rd-year student at CHRIST University, India. I have been selected to GSoC 2022 as a mentee in KDE. This blog will track my KDE development work during, and after, GSoC coding period.

About the Project:

Flatpak and Snap applications run inside sandboxes, isolated from the rest of the system, and do not have access to many critical resources. As a result, they often cannot do much, and must seek permission to access the resources they require. Flatpaks access these permissions through “portals”, and Snaps do it via “interfaces”. At installation time, these permissions are usually granted by default. Presently, KDE lacks a home-grown mechanism to edit these permissions.

My SoK 2022 Project had two parts: the first was to display these permissions on Discover’s interface, and the second to develop a mechanism (through a KCM module, it was decided) to let users change these permissions. The first segment of the project was accomplished, but the second was leftover.

This GSoC project involves creating the KCM module for Flatpak, and also showing Snap permissions on Discover’s interface in the same way as Flatpaks, as well as creating KCM modules for Snaps.

So far, I have created the repository for Flatpak KCM here.

About Me:

I am a 20-year-old from India, currently pursuing a BTech at Computer Science and Engineering. I have been programming for about 2 years, chiefly in C++, C and Python. I use Fedora KDE as my daily driver, and have been a KDE user for a year. In my free time, I read books on history and politics, and have been getting into Chess lately.

Feel free to contact me if you have any suggestions!

Categories: FLOSS Project Planets

John Goerzen: Really Enjoyed Jason Scott’s BBS Documentary

Planet Debian - Mon, 2022-06-13 20:13

Like many young programmers of my age, before I could use the Internet, there were BBSs. I eventually ran one, though in my small town there were few callers.

Some time back, I downloaded a copy of Jason Scott’s BBS Documentary. You might know Jason Scott from textfiles.com and his work at the Internet Archive.

The documentary was released in 2005 and spans 8 episodes on 3 DVDs. I’d watched parts of it before, but recently watched the whole series.

It’s really well done, and it’s not just about the technology. Yes, that figures in, but it’s about the people. At times, it was nostalgic to see people talking about things I clearly remembered. Often, I saw long-forgotten pioneers interviewed. And sometimes, such as with the ANSI art scene, I learned a lot about something I was aware of but never really got into back then.

BBSs and the ARPANet (predecessor to the Internet) grew up alongside each other. One was funded by governments and universities; the other, by hobbyists working with inexpensive equipment, sometimes of their own design.

You can download the DVD images (with tons of extras) or watch just the episodes on Youtube following the links on the author’s website.

The thing about BBSs is that they never actually died. Now I’m looking forward to watching the Back to the BBS documentary series about modern BBSs as well.

Categories: FLOSS Project Planets

Plasma 5.25

Planet KDE - Mon, 2022-06-13 20:00
A host of new features and cool fresh concepts in Plasma 5.25 give you a peek into the future of KDE’s desktop. Highlights Gestures

Gestures on touchpads and touchscreens put Plasma at your fingertips

Colors

Bored of grey? Plasma puts a literal rainbow of possibilities at your disposal

Tailor-made

Customizing your desktop has never been easier... or more fun!

Navigate Workspaces

KDE Plasma 5.25 redesigns and enhances how you navigate between windows and workspaces.

Overview

The Overview effect shows all of your open windows and virtual desktops.

You can search for apps, documents, and browser tabs with KRunner and the Application Launcher.

You can add, remove, and rename virtual desktops.

Hold down the Meta (“Windows”) key and press W to enter Overview mode or use a four-finger pinch on your trackpad. Gestures

On your touchpad:

A four-finger pinch opens the Overview. A three-finger swipe in any direction will switch between Virtual Desktops. A downwards four-finger swipe opens Present Windows. A four-finger upwards swipe activates the Desktop Grid.

On your touchscreen:

You can configure swipes from the screen edge to open Overview, Desktop Grid, Present Windows, and Show Desktop as they directly follow your finger.

Open System Settings and pick the open Workspace Behavior tab, and then Touch Screen. Click on any of the squares shown on the sides of the monitor icon and a dropdown will open. Select Overview, Desktop Grid, Present Windows, or Desktop Grid and click Apply. Now you can slide your finger from the edge of the screen you selected towards the middle of the screen and watch the magic happen.

Colors

Sync the accent color with your wallpaper! The dominant color of your background picture can be applied to all components that use the accent color.

Open System Settings and choose the Appearance tab, then Colors. Select From current wallpaper and click Apply. It is that easy.

With slideshow wallpapers, colors update when the wallpaper changes.

Tint all colors of any color scheme using the accent color and adapt the color of elements of every window to the background. You can also choose how much tint you’d like to see mixed in with your normal color scheme.

Open System Settings and then click on the Appearance tab. Choose Colors and click on the Edit icon (the little pencil button) in the lower-right corner of a color scheme preview and a configuration dialogue will open. In the Options tab, tick the Tint all colors with the accent colors box and slide Tint strength: to the desired value. Click Save as and give your color scheme a new name. Click Close. Select your newly created color scheme and click Apply.

While configuring your color scheme, you can also make the header area or titlebar use the accent color.

Touch and Feel

Activate Touch Mode by detaching the screen, rotating it 360°, or enabling it manually.

If your laptop supports detaching or rotating back the keyboard, do that now. Touch Mode will activate. If not, you can manually enable Touch Mode by opening System Settings, clicking on the Workspace Behavior tab, and selecting the Touch Mode: Always Enabled radio button at the end of the page.

The Task Manager and the System Tray become bigger when in Touch Mode making it easier on your fingers. You can customize the size of the icons when Touch Mode is disabled, too.

To manually increase icon spacing in the Task Manager, right-click the Task Manager and select Configure Icons-Only Task Manager. Select Large in the Spacing between icons: option. To manually increase the icon spacing in the System Tray, right-click on the System Tray and select Configure System Tray. Select Large in the Panel icon spacing: option.

Titlebars of KDE apps become taller when in Touch Mode, making it easier to press, drag, and close windows with touch. Context menu items become taller when in Touch Mode, giving you more space to tap the correct one.

Customization

Floating Panels add a margin all around the panel to make it float, while animating it back to look normal when a window is maximized.

Right-click the panel, select Enter Edit Mode, and then More Options. Select Floating.

Blend Effects gracefully animate the transition when color schemes are changed.

Move your entire desktop, with folders, widgets and panels, from one monitor to another with the Containment Management window.

Right-click on the desktop and select Enter Edit Mode. Choose Manage Desktop and Panels from the top toolbar and drag and drop desktops or panels from one display to another, or click on their hamburger menu.

Other Updates
  • The Global Theme settings page lets you pick and choose which parts to apply so you can apply only the parts of a global theme that you like best.

  • The Application page for Discover has been redesigned and gives you links to the application’s documentation and website, and shows what system resources it has access to.

  • If you get your password wrong, the lock and login screens shake, giving you a visual cue to try again.

  • The KWin Scripts settings page has been rewritten making it easier to manage your window manager scripts.

  • Plasma panels can now be navigated with the keyboard, and you can assign custom shortcuts to focus individual panels.

Hold down the Meta (“Windows”) and Alt keys, then press P to cycle focus between all your panels and navigate between their widgets with the arrow keys. You can also right-click a panel and select Enter Edit Mode. Then choose More Options so you can set a custom shortcut to focus that particular panel.

… And there’s much more going on. If you would like to see the full list of changes, check out the changelog for Plasma 5.25.

Categories: FLOSS Project Planets

Kate + Building in Docker

Planet KDE - Mon, 2022-06-13 18:00

Have I said nice things about Kate recently? Not enough, so let me gush a little about Kate as an “IDE” and using it, with the Build Plugin, as a tool for editing locally and building remotely.

I work on a codebase that has very specific platform requirements. These requirements are difficult to reproduce in a normal host – or, if you have some modern rolling distro like openSUSE, well-nigh-impossible. That’s the situation where Docker shows up, since a Docker container can be whatever specific platform is needed.

So I have a Docker, with the special compilation environment over here, and the host machine, running a recent version of Kate over there. How can I make them work together?

Sharing Directories with Docker

When starting a Docker container with docker run, you can bind-mount locations into the container. So for a builder-container, where you want to have the source code available inside, a convenient way to do it is to bind-mount the source directory in the host, to a location – the same location – in the container.

Something like this:

docker run \ -v /home/me/src/myproject:/home/me/src/myproject:rw \ --name myproject \ myprojectimage \ /bin/sh

The --name argument is slightly-important. Docker comes up with a creative random name of the container if you don’t give one explicitly, and that makes it harder to connect to the running container.

I should note that my approach is “leave the container running, and connect to it for compilation”, not “start a new container for every build”. Your mileage may vary, and it’s easy enough to bung some commands to start a container and run make in it, in a shell script and use that.

Configuring the Build-in-Docker

The codebase I’m on uses CMake as meta-buildsystem, which leads to the usual (?) convention: there’s a build/ dir underneath the sources, CMake is run there, and then the build proceeds there as well:

# Do this in the container mkdir /home/me/src/myproject/build cd /home/me/src/myproject/build cmake ..

When doing a build like this, Qt’s moc will generate files in (subdirectories-of) the build/ directory; other sources might be generated there as well. Compiler errors might reference absolute paths (e.g. /home/me/src/myproject/main.cc) or might reference relative paths (e.g. ../main.cc).

Depending on the exact way Docker is run from the host, the build directory may or may not be visible. For me, it isn’t, and for various reasons I can’t create the same build/ path in the host. So instead, I create a similar path that leads to the same relative paths back to the source directory:

# Do this in the host mkdir /home/me/src/myproject/build_ Setting up Kate-in-Host

This is the main course: using Kate as an IDE, running the build inside the Docker container.

First, we need to enable the Build Plugin. Kate comes with a bunch of plugins that provide extra search functionality, IDE functionality, better LaTeX support, .. it’s quite extensive. Go to SettingsConfigure Kate.. and choose the Plugins pane (module? I don’t really know what those icons-in-a-column should be called, each of which calls up its own set of tabs). Tick the box in front of the Build Plugin.

Kate Plugin List, with *Build Plugin* checked

Unfortunately, the Build Plugin doesn’t initialize quite right when enabled the first time. Quit Kate, then start it again.

Once it’s back, there is a Build button at the bottom of the window. Click on it to open up the tool view for the plugin. There are target sets, and there’s a top-level “name of the target set” and “working directory” – since this is laid out in a two-column table it looks a bit strange.

Kate Plugin List, with *Build Plugin* checked

The Kate Documentation for the Build Plugin is reasonably extensive.

  • Optionally, click on the T: Target Set label to change the name of the set.
  • Click on the Dir: label to change the directory where the build happens. This is needed because otherwise the build happens either where Kate was started, or the directory where the current file is. I haven’t got a clear answer on that.
  • Tick the box in front of build to make it the default target to build.
  • Click on the make command to edit it.
  • Fill in the command to run the build in the container. I use Docker’s run command, with the name of the container to attach to. -a is a flag to preserve stdin, out, and error. The make command changes directory to the actual build-directory, and -j is tuned to the available CPU power. docker run -a myproject \ make -C /home/me/src/myproject/build -j4

There’s a little cog-like icon with tooltip Build selected target. Click on the build line to select it, then hit the cog and see what happens.

Personally I like the KDevelop key-binding of F8 for “build the thing”, so I open the Build menu (top of the Kate window), right-mouse-click on the menu entry Build Default Target, pick Configure Shortcut.. and bind F8 to it. By default, that key is bound to “switch to next view”, but I don’t use split views.

O noes, Ninja

The Build Plugin parses the output of the build command – e.g. make. The Build Plugin also knows how to deal with Ninja. However – and thanks to Christoph Cullmann for helping figure this out – Kate uses a trick to separate the Ninja output from compiler output (with make, this is apparently not needed). The environment variable NINJA_STATUS gets special treatment from Kate. The variable needs to be passed in to the container, so for a ninja build this is the Docker command (where -e NINJA_STATUS means “pass the value of the environment variable in to the container”).

docker run -a myproject \ -e NINJA_STATUS \ make -C /home/me/src/myproject/build -j4 Takeaway

With just a few steps, building a weird-ass codebase in a container can be a lot more pleasant by editing it outside the container with modern tools, and “remote build” is supported by Kate quite well.

If you wonder why I’m not using KDevelop, well, two things: it actually has less documentation on custom and remote builds, and two, it crashes just trying to read the weird-ass codebase. I have yet to debug the latter.

Categories: FLOSS Project Planets

Chris Moffitt: Using Document Properties to Track Your Excel Reports

Planet Python - Mon, 2022-06-13 15:25
Introduction

When doing analysis with Jupyter Notebooks, you will frequently find yourself generating ad-hoc Excel reports to distribute to your end-users. After time, you might end up with dozens (or hundreds) of notebooks and it can be challenging to remember which notebook generated which Excel report. I have started using Excel document properties to track which notebooks generate specific Excel files. Now, when a user asks for a refresh of a 6 month old report, I can easily find the notebook file and re-run the analysis. This simple process can save a lot of frustration for your future self. In this brief article will walk through how to set these properties and give some shortcuts for using VS Code to simplify the process.

Background

How often has this happened to you? You get an email from a colleague and they ask you to refresh some analysis you did for them many months ago? You can tell that you created the Excel file from a notebook but can’t remember which notebook you used? Despite trying to be as organized as possible it is inevitable that you will waste time trying to find the originating notebook.

The nice aspect of the Excel document properties is that most people don’t change them. So, even if a user renames the file, the properties you set will be easily visible and should point the way to where the original code sits on your system.

Adding Properties

If you’re using pandas and xlsxwriter, adding properties is relatively simple.

Here’s a simple notebook showing how I typically structure my analysis:

import pandas as pd from pathlib import Path from datetime import datetime today = datetime.now() report_file = Path.cwd() / 'reports' / f'sales_report_{today:%b-%d-%Y}.xlsx' url = 'https://github.com/chris1610/pbpython/blob/master/data/2018_Sales_Total_v2.xlsx?raw=True' df = pd.read_excel(url)

The important point is that I try to always use a standard naming convention that includes the date in the name as well as a standard directory structure.

Now, I’ll do a groupby to show sales by month for each account:

sales_summary = df.groupby(['name', pd.Grouper(key='date', freq='M')]).agg({ 'ext price': 'sum' }).unstack()

Here’s what the basic DataFrame output looks like:

The final step is to save the DataFrame to Excel using the pd.ExcelWriter context manager and set the document properties:

with pd.ExcelWriter(report_file, engine='xlsxwriter', date_format='mmm-yyyy', datetime_format='mmm-yyyy') as writer: sales_summary.to_excel(writer, sheet_name='2018-sales') workbook = writer.book workbook.set_properties({ 'category': r'c:\Users\cmoffitt\Documents\notebooks\customer_analysis', 'title' : '2018 Sales Summary', 'subject': 'Analysis for Anne Analyst', 'author': '1-Excel-Properties.ipynb', 'status': 'Initial draft', 'comments': 'src_dir: customer_analysis', 'keywords': 'notebook-generated' })

Once this is done, you can view the properties in a couple of different ways.

First, you can hover over the filename and get a quick view:

You can also view the details without opening Excel:

You can view the properties through Excel:

As you can see from the example, there are a handful of options for the properties. I encourage you to adjust these based on your own needs. For example, I save all of my work in a notebooks directory so it’s most useful to me to specify the src_dir in the Comments section. This will quickly point me to the right directory and the Authors property lets me know which specific file I used.

Observant readers will notice that I used this as an example to show how to adjust the date formats of the Excel output as well. As you can see below, I have adjusted the Excel output so that only the month and year are shown in the header. I find this much easier than going in and adjusting every example by hand.

Here’s what it looks like now:

Using VS Code Snippets

If you find this helpful, you may want to set up a snippet in VS Code to make this easier. I covered how to create snippets in this article so refer back to that for a refresher.

Here is a starter snippet to save the file to Excel and populate some properties:

"Write Excel": { "prefix": "we", "body": [ "# Excelwriter", "with pd.ExcelWriter(report_file, engine='xlsxwriter', date_format='mmm-yyyy', datetime_format='mmm-yyyy') as writer:", "\t$1.to_excel(writer, sheet_name='$2')", "\tworkbook = writer.book", "\tworkbook.set_properties({'category': r'$TM_DIRECTORY', 'author': '$TM_FILENAME'})", ], "description": "Write Excel file" }

One nice benefit of using the snippet is that you can access VS Code variables such as $TM_DIRECTORY and $TM_FILENAME to pre-populate the current path and name.

Conclusion

When working with Jupyter Notebooks it is important to have a consistent process for organizing and naming your files and directories. Otherwise the development process can get very chaotic. Even with good organization skills, it is easy to lose track of which scripts generate which outputs. Using the Excel document properties can be a quick and relatively painless way to lay out some breadcrumbs so that it is easy to recreate your analysis.

Let me know in the comments if you have any other tips you’ve learned over the years.

Categories: FLOSS Project Planets

Ben Hutchings: Debian LTS work, May 2022

Planet Debian - Mon, 2022-06-13 14:30

In May I was assigned 11 hours of work by Freexian's Debian LTS initiative and carried over 13 hours from April. I worked 8 hours, and will carry over the remaining time to June.

I spent some time triaging security issues for Linux, working out which of them were fixed upstream and which actually applied to the versions provided in Debian 9 "stretch". I rebased the Linux 4.9 (linux) package on the latest stable update, but did not make an upload this month. I started backporting several security fixes to 4.9, but those still have to be tested and reviewed.

Categories: FLOSS Project Planets

Talking Drupal: Talking Drupal #351 - Core Theming $h!t

Planet Drupal - Mon, 2022-06-13 14:00

Today we are talking about Core Theming with Cristina Chumillas.

www.talkingDrupal.com/351

Topics
  • What’s newe in core themeing?
  • Why is Claro in core important?
  • Why is Olivero in core important?
  • Why was it so long between new themes?
  • Continuous improvement?
  • What is the biggest improvement?
  • What happens to old themes?
  • Accessibility
  • CSS
    • Build tools
  • Drupal 10
    • IE
    • UC
  • Compound elements
  • Getting involved
Resources Guests Hosts

Nic Laflin - www.nLighteneddevelopment.com @nicxvan John Picozzi - www.epam.com @johnpicozzi Mike Herchel - herchel.com - @mikeherchel

MOTW

Quicklink This module provides an implementation of Google Chrome Lab’s Quicklink library for Drupal. Quicklink is a lightweight (< 1kb compressed) JavaScript library that enables faster subsequent page-loads by prefetching in-viewport links during idle time.

Categories: FLOSS Project Planets

Edward Betts: Fixing spelling in GitHub repos using codespell

Planet Debian - Mon, 2022-06-13 13:24

Codespell is a spell checker specifically designed for finding misspellings in source code.

I've been using it to correct spelling mistakes in GitHub repos sine 2016.

Most spell checkers use a list of valid words and highlighting any word in a document that is not in the word list. This method doesn't work for source code because code contains abbreviations and words joined together without spaces, a spell checker will generate too many false positives.

Codespell uses a different approach, instead of a list of valid words it has a dictionary of common misspellings.

Currently the codespell dictionary includes 34,466 known misspellings. I've contributed 300 misspellings to the dictionary.

Whenever I find an interesting open source project I run codespell to check for spelling mistakes. Most projects have spelling mistakes and I can send a pull request to fix them.

In 2019 Microsoft made the Windows calculator open source and uploaded it to GitHub. I used codespell to find some spelling mistakes, sent them a pull request and they accepted it.

A great source for GitHub repos to spell check is Hacker News. Let's have a look.

Hacker News has a link to forum software called Flarum. I can use codespell to look for spelling mistakes. When I'm looking for errors in a GitHub repo I don't fork the project until I know there is a spelling mistake to fix.

edward@x1c9 ~/spelling> git clone git@github.com:flarum/flarum.git Cloning into &aposflarum&apos... remote: Enumerating objects: 1338, done. remote: Counting objects: 100% (42/42), done. remote: Compressing objects: 100% (23/23), done. remote: Total 1338 (delta 21), reused 36 (delta 19), pack-reused 1296 Receiving objects: 100% (1338/1338), 725.02 KiB | 1.09 MiB/s, done. Resolving deltas: 100% (720/720), done. edward@x1c9 ~/spelling> cd flarum/ edward@x1c9 ~/spelling/flarum (master)> codespell -q3 ./public/web.config:13: sensitve ==> sensitive edward@x1c9 ~/spelling/flarum (master)> gh repo fork ✓ Created fork EdwardBetts/flarum ? Would you like to add a remote for the fork? Yes ✓ Added remote origin edward@x1c9 ~/spelling/flarum (master)> git checkout -b spelling Switched to a new branch &aposspelling&apos edward@x1c9 ~/spelling/flarum (spelling)> codespell -q3 ./public/web.config:13: sensitve ==> sensitive edward@x1c9 ~/spelling/flarum (spelling)> codespell -q3 -w FIXED: ./public/web.config edward@x1c9 ~/spelling/flarum (spelling)> git commit -am "Correct spelling mistakes" [spelling bbb04c7] Correct spelling mistakes 1 file changed, 1 insertion(+), 1 deletion(-) edward@x1c9 ~/spelling/flarum (spelling)> git push -u origin Enumerating objects: 7, done. Counting objects: 100% (7/7), done. Delta compression using up to 8 threads Compressing objects: 100% (4/4), done. Writing objects: 100% (4/4), 360 bytes | 360.00 KiB/s, done. Total 4 (delta 3), reused 0 (delta 0), pack-reused 0 remote: Resolving deltas: 100% (3/3), completed with 3 local objects. remote: remote: Create a pull request for &aposspelling&apos on GitHub by visiting: remote: https://github.com/EdwardBetts/flarum/pull/new/spelling remote: To github.com:EdwardBetts/flarum.git * [new branch] spelling -> spelling branch &aposspelling&apos set up to track &aposorigin/spelling&apos. edward@x1c9 ~/spelling/flarum (spelling)> gh pr create Creating pull request for EdwardBetts:spelling into master in flarum/flarum ? Title Correct spelling mistakes ? Choose a template Open a blank pull request ? Body <Received> ? What&aposs next? Submit https://github.com/flarum/flarum/pull/81 edward@x1c9 ~/spelling/flarum (spelling)>

That worked. I found one spelling mistake, the word "sensitive" was spelled wrong. I forked the repo, fixed the spelling mistake and submitted the fix as a pull request.

The maintainer of Flarum accepted my pull request.

Fixing spelling mistakes in Bootstrap helped me unlocked the Mars 2020 Contributor achievements on GitHub.

Why not try running codespell on your own codebase? You'll probably find some spelling mistakes to fix.

Categories: FLOSS Project Planets

Pages