Springe zum Inhalt →

Schlagwort: Python

Todo.txt – Die einfache ToDo Liste

Ich bin immer auf der Suche nach eine Möglichkeit meine Aufgaben zu notieren, damit ich auch nichts vergesse. Und so habe ich über die Jahre schon viele ToDo Programme durchprobiert. Nicht viele haben mich langfristig an der Stange gehalten.

Im Büro verwende ich Outlook. Als zentrale Stelle für Kalender und Emails ist es auch der richtige Ort für meine Aufgaben. Und die Kopplung zu OneNote ist mehr als gut. Zusätzlich habe ich noch ein paar Helferlein, die meine Arbeitsweise noch mehr unterstützen.

Jedoch steht mir diese Umgebung privat nicht zur Verfügung. Ich habe etwas gesucht, dass einfach und über alle meine Systeme hin benutzbar ist. Und dabei bin ich auf eine simple Textdatei gestoßen.

ToDo.txt ist nicht nur der Name der Textdatei, nein es ist ein ganzes System ausgedacht von Gina Trapani. Sie hat diverse Namenskonventionen festgelegt, um in einer simplen Textdatei Aufgaben zu sortieren und bearbeiten. Alles nachzulesen auf dieser Seite.

So sieht eine Zeile und damit eine Aufgabe im Maximum aus.

Das erste Zeichen „x“ ist die Checkbox, ob eine Aufgabe erledigt ist oder nicht. Gefolgt von der Priorität in runden Klammern. Danach Data für den Abschluss und Erstellung. Gefolgt vom eigentlichen Aufgabentext und den Merker für Projekte „+“ und Kontext „@“. Zum Schluss die Deadline.

Wie man sieht, beinhaltet die Zeile alle Informationen die notwendig sind. Und mit einem ordentlichen Texteditor wie unser beliebtes Notepad++ kann man ohne Probleme z.B. alle Zeilen die als Projekt „+Wohnung“ haben sofort finden. So habe ich eine Zeitlang alle meine Aufgaben verwaltet. Einen kleinen Teaser habe ich ja in meinem „Jedi Tricks – Windows – Tastatur Shortcuts“ Beitrag erwähnt.

Und damit sind wir bei dem riesen Vorteil dieser Methode. Die Textdatei kann mit Allem bearbeitet werden und ist damit super flexibel. Und das eröffnet auch gleich alle Tore, um allerlei kompatible Programme zu erstellen. Sehr viele findet man auf der Homepage https://todotxt.org/

Nachdem ich vom Notepad++ als ToDo.txt Editor weggegangen bin, habe ich das kleine portable Tool todotxt.net verwendet. Eine simple GUI mit vielen Keyboard Shortcuts. Genau was ich liebe.

Trotzdem habe ich immer sehr neidisch auf Gina geschaut. Denn das eigentliche Tool, das Sie geschrieben hat, ist ein Kommandozeilen Tool (cli – command line interpreter). Wunderschön und simpel, aber nur für Mac oder Linux. Für Windows / DOS gibt es leider nichts.

Also gab es nur eine Möglichkeit. „Massimo setzt dich hin und programmiere es selbst!

Und so ist es entstanden. Ich habe mir ein rudimentäres Grundgerüst geklont und die letzten Tage immer mehr Features ran gebaut. Jetzt habe ich ein kleines feines Python Programm, dass meine ToDo.txt nach den Regeln bearbeitet. Es ist noch nicht ganz fertig und ich werde noch mehr Funktionen einbauen, die den Tastaturkürzeln von todotxt.net entsprechen.

Ich nehme gerne Wünsche und Anregungen entgegen. Downloaden und Kommentieren könnt Ihr es auf der dazugehörigen Github Seite.


Kommentare sind geschlossen.

Jedi Tricks – Python – Bilder sortieren à la Tinder

Wenn man sein Mobiltelefon wechselt oder einfach mal nur aufräumen will, dann kann es passieren, dass meine einen Ordner mit hunderten von Bildern hat, von denen man jedoch nur dutzende Aufheben will. Typisch für so ein Fall ist der WhatsApp Medien Ordner.

Jetzt kann man natürlich mit IrfanView sich von Bild zu Bild klicken, anschauen und dann löschen. Das ist jedoch nicht schnell und löschen und weiterklicken geht nicht sehr flüssig von der Hand. Und Bilder, die man behalten will, bleiben dann immer „übrig“. Wenn man am nächsten Tag weiter sortieren will, stören sie.

Auf Android gibt es die App SlideBox, die das Problem wie bei Tinder löst. Sie zeigt ein Bild an, man swiped in eine Richtung um es zu löschen, in eine Andere um es zu behalten. Das geht locker von der Hand. Aber am PC gibt es sowas nicht.

Und da ich nicht nur immer sage, dass man mehr programmieren sollte, habe ich mich hingesetzt und quick und dirty etwas zusammengeschrieben.

Den Quelltext habe ich auf meinem Github abgelegt. Gerne zum Downloaden und verwenden. Es setzt Python, TKinter und OpenCV voraus. Python sollte meiner Meinung nach immer auf einem Rechner installiert sein. Ab der Version 3.x ist TKinter mit dabei. OpenCV bekommt man einfach per:

pip install opencv-python

Ich gehe hier kurz auf das Skript ein.

import tkinter as tk
from tkinter import filedialog
import os
import cv2
import sys
import shutil

# output folder
sort = "e:/pic_swipe/sort/"
todelete = "e:/pic_swipe/delete/"

Zuerst werden die benötigten Pakete importiert.

TKinter brauchen wir für den Dateidialog. OS, SYS und SHUTIL für das Dateihandling und CV2 ist OpenCV um die Bilder zu betrachten und auch die Cursortasten abzufragen und mit Funktionen zu versehen.

Dann werden die Ausgabeverzeichnisse definiert. Man braucht ein Ordner in der die zu Löschenden und in der die zu behaltenden Dateien abgelegt werden sollen. Ja, die Ordner habe ich im ersten Wurf hart reingecoded. Das Skript hat noch ein paar weitere Schönheitsfehler. Das sollte jedoch nicht stören, wir brauchen eine Abhilfe für unser Problem.

# File dialog for picing picture folder
root = tk.Tk()
root.withdraw()
file_path = os.path.dirname(filedialog.askopenfilename())

Diese Zeilen öffnen einen Dateidialog. Man wählt damit eine Bilddatei in dem zu sortierenden Verzeichnis aus. Das Verzeichnis wird in der Variable „file_path“ gesichert.

# content of picutre folder
picturelist = os.listdir(file_path)
index = 0

Damit wird das Verzeichnis ausgelesen. Der Inhalt in die Liste „picturelist“ gesichert und die Indexvariable initialisiert.

# create viewer windows, resize picture
cv2.namedWindow("image", cv2.WINDOW_NORMAL)
img = cv2.imread(filename = str(file_path)+"/"+str(picturelist[index]))
cv2.resizeWindow('image',800, 600)
cv2.imshow('image',img)

Mit OpenCV erstellen wir das Viewerfenster und legen es auf 800×600 Pixel fest. Und laden das erste Bild (Eintrag Index 0 der Liste). Alle Bilder, die angezeigt werden, werden auch das Format „gepresst“. Ja, das verreißt die Proportionen, aber wir wollen die Bilder nicht bearbeiten, sondern nur kurz anschauen, um dann zu entscheiden, ob ins Töpfchen oder ins Kröpfchen.

while(1):
    k = cv2.waitKeyEx(0)
    if k==27:           # wait for ESC key to exit
        cv2.destroyAllWindows()
        break

Und damit sind wir schon bei der Hauptschleife. Diese läuft mit while(1) unendlich. Mit cv2.waitKexEx(0) überprüfen wir welche Taste gedrückt wird und speichern dies in die Variable „k“.

„27“ ist der Code für die ESC Taste mit der die While Schleife unterbrochen und damit das Programm beendet wird.

    elif k==2490368:    # cursor up move to delete folder
        shutil.move(str(file_path)+"/"+str(picturelist[index]), str(todelete)+"/"+str(picturelist[index]))
        index += 1
        img = cv2.imread(filename = str(file_path)+"/"+str(picturelist[index]))
        cv2.resizeWindow('image',800, 600)
        cv2.imshow('image',img)    

„2490368“ Pfeiltaste hoch. Damit verschieben wir die aktuell angezeigte Datei in den Löschen-Ordner. Erhöhen den Index um 1 und zeigen damit das nächste Bild an. Damit entsteht der Flow. Keine weitere Taste drücken um das nächste Bild zu bearbeiten.

    elif k==2621440:    #cursor down move to sort folder
        shutil.move(str(file_path)+"/"+str(picturelist[index]), str(sort)+"/"+str(picturelist[index]))
        index += 1
        img = cv2.imread(filename = str(file_path)+"/"+str(picturelist[index]))
        cv2.resizeWindow('image',800, 600)
        cv2.imshow('image',img)

„2621440“ Pfeiltaste runter. Das Bild wird in den Sortieren-Ordner verschoben und auhc hier gleich die nächste Datei angezeigt.

    elif k==2424832:    # cursor left previous picture
        index -= 1
        if index < 0:
            index = 0
        img = cv2.imread(filename = str(file_path)+"/"+str(picturelist[index]))
        cv2.resizeWindow('image',800, 600)
        cv2.imshow('image',img)
    elif k==2555904:    # cursor right next picture
        index += 1
        img = cv2.imread(filename = str(file_path)+"/"+str(picturelist[index]))
        cv2.resizeWindow('image',800, 600)
        cv2.imshow('image',img)
    elif k==-1:         # ignore waitkey standard input
        continue
    else:               # print every other pressed key
        print(k)    

Die restlichen Abfragen sind nur noch Makulatur. „2424832“ Pfeiltaste links um zum vorherigen Bild zu gelangen und „2555904“ Pfeiltaste rechts um zum nächsten zu kommen. „-1“ brauchen wir, da waitKeyEx die Tasten immer wieder abfragt und -1 zurückgibt, wenn nichts betätigt wird. Und zum Schluss noch eine Ausgabe, wenn man eine andere Taste drückt. Mit diesem Print sieht man den Code der Taste.

Wie man unschwer erkennen kann, fange ich zwar einen Index kleiner 0 ab, aber den höchsten Index, d.h. nach der letzten Bilddatei, nicht. Auch läuft das Skript auf einen Fehler, wenn man ein Bild verschoben hat und dann zurück (Pfeil links) auf das Bild springt. Das ist dann nicht mehr da und OpenCV steigt mit einem Fehler aus.

Es gibt also noch ein paar Dinge zu erledigen. Z.B. den Code zum Bildanzeigen habe ich 5 mal „getippt“, dass schreit förmlich nach einer Subroutine.

Ihr könnt euch gerne austoben und auf mein Git die Änderungen commiten.

Bei Fragen könnt Ihr Euch gerne an mich wenden. Unten werde ich das komplette Skript nochmals einfügen, eine aktuellere Version werdet Ihr immer auf Github finden.

Viel Spaß mit dem Skript und beim Sortieren der Bilder.

import tkinter as tk
from tkinter import filedialog
import os
import cv2
import sys
import shutil

# output folder
sort = "e:/pic_swipe/sort/"
todelete = "e:/pic_swipe/delete/"

# File dialog for picing picture folder
root = tk.Tk()
root.withdraw()
file_path = os.path.dirname(filedialog.askopenfilename())

# content of picutre folder
picturelist = os.listdir(file_path)
index = 0

# create viewer windows, resize picture
cv2.namedWindow("image", cv2.WINDOW_NORMAL)
img = cv2.imread(filename = str(file_path)+"/"+str(picturelist[index]))
cv2.resizeWindow('image',800, 600)
cv2.imshow('image',img)

while(1):
    k = cv2.waitKeyEx(0)
    if k==27:           # wait for ESC key to exit
        cv2.destroyAllWindows()
        break
    elif k==2490368:    # cursor up move to delete folder
        shutil.move(str(file_path)+"/"+str(picturelist[index]), str(todelete)+"/"+str(picturelist[index]))
        index += 1
        img = cv2.imread(filename = str(file_path)+"/"+str(picturelist[index]))
        cv2.resizeWindow('image',800, 600)
        cv2.imshow('image',img)
    elif k==2621440:    #cursor down move to sort folder
        shutil.move(str(file_path)+"/"+str(picturelist[index]), str(sort)+"/"+str(picturelist[index]))
        index += 1
        img = cv2.imread(filename = str(file_path)+"/"+str(picturelist[index]))
        cv2.resizeWindow('image',800, 600)
        cv2.imshow('image',img)
    elif k==2424832:    # cursor left previous picture
        index -= 1
        if index < 0:
            index = 0
        img = cv2.imread(filename = str(file_path)+"/"+str(picturelist[index]))
        cv2.resizeWindow('image',800, 600)
        cv2.imshow('image',img)
    elif k==2555904:    # cursor right next picture
        index += 1
        img = cv2.imread(filename = str(file_path)+"/"+str(picturelist[index]))
        cv2.resizeWindow('image',800, 600)
        cv2.imshow('image',img)
    elif k==-1:         # ignore waitkey standard input
        continue
    else:               # print every other pressed key
        print(k)    
Schreibe einen Kommentar