QApplication::setOverrideCursor(Qt::WaitCursor); // cursor a reloj
ret = translationJob(orgLang, targetLang,strFrom,&strReturned);
QApplication::restoreOverrideCursor(); // cursor a normal
QApplication::setOverrideCursor(Qt::WaitCursor); // cursor a reloj
ret = translationJob(orgLang, targetLang,strFrom,&strReturned);
QApplication::restoreOverrideCursor(); // cursor a normal
El tema de la extracción de subtitulos de contenedores matroska se está convirtiendo en un tema recurrente. Se ha tratado en 2011, revisado en 2018 y aquí está la versión de 2023.
Herramientas para utilizar con Debian 11.
Obtención de información en linea de comandos:
mkvinfo ma.mkv
Obtención de información con gui:
Extracción de la pista de subtítulos
Hay que tener en cuenta que mkvinfo numera las pistas de forma distinta que mkvextract. mkvinfo cuenta las pistas empezando por 1 y en mkvextract, la primera pista es la 0. La salida de mkvinfo muestra:
+ Número de pista: 3 (ID de pista para mkvmerge y mkvextract: 2)| + Pista UID: 10888806681018786732
| + Tipo de pista: Subtítulos
| + Marcador de atadura: 0
| + ID del códec: S_TEXT/ASS
Los subtítulos están en formato ASS. Aparece como pista 3, por tanto en mkvextract hay solicitar la pista 2.
mkvextract tracks ma.mkv 2:subti.srt
mkvextract ignora la extensión del archivo de salida, por tanto, si contendor matroska contine subtitulos en formato ass, mkvextract gerera un archivo en formato ass. Por tanto hay que convertir el archivo de subtítulos formato srt. Hay que señalar que si no se necesita específicamente el formato srt, el formato ass tiene más características.
Conversión de formato de los subtítulos de ass a srt.
ffmpeg -i subti.ass -codec:s srt subti2.srt
mas cosas
1.1. Enviar notificaciones al escritorio gráfico: notify-send
Instalar lib-notify-bin. Tutorial
Uso:
notify-send -a "Dell control" "Este script no funciona sin un parámetro."
Encender:
xrandr --output $SALIDA --auto --right-of HDMI-A-0
Apagar:
xrandr --output $SALIDA --off
if [ -z "$1" ]; then
notify-send -a "Dell control" "Este script no funciona sin un parámetro."
echo "no hay parámetro. abortar"
exit 1
fi
INFO=`xrandr |grep $SALIDA`
echo "info: $INFO"
PRIMERO=`echo "$INFO" | awk '{print $1}'`
echo "PRI: $PRIMERO"
if [ "$PRIMERO" != "$SALIDA" ] ; then
echo "No se encuentra patalla $SALIDA."
notify-send -a "Dell control" "No se encuentra la pantalla $SALIDA."
exit 1
fi
La parte más oscura es comprobar el estado del monitor. El comando randr muestra una sutil diferencia entre el estado del monitor encendido y o apagado. Cuando está encendido muestra las medidas físicas del monitor; apagado, no.
Encendido:
DVI-D-0 connected 1680x1050+1920+0 (normal left inverted right x axis y axis) 473mm x 296mm
Apagado:
DVI-D-0 connected (normal left inverted right x axis y axis)
ULTIMA_PALABRA=`echo "$INFO" | awk '{print $NF}'`
if [[ $ULTIMA_PALABRA == *"mm" ]]; then
# Si la última parabra es una medida, el monitor está activo. apagarlo
echo "Esta activo. Apagar"
xrandr --output $SALIDA --off
notify-send -a "Dell control" "monitor auxiliar $SALIDA apagado."
else
# el monitor no está activo. encenderlo
echo "No esta activo. Encender"
xrandr --output $SALIDA --auto --right-of HDMI-A-0
notify-send -a "Dell control" "Monitor auxiliar $SALIDA encendido."
fi
firefox: conguración en about:config
Versión 102:
Versión 103+:
javascript
document.getElementById('boton13').onclick = function (){
navigator.clipboard.readText()
.then((text) => {
if (text=="")
{
alert ("El portapapeles está vació o el contenido no es texto.")
return;
}
insertText(text);
})
.catch((err) => {
alert("Error al leer el portapapeles");
console.error('Error al leer del portapapeles: ', err);
});
}
Válido para Debian 12
/etc/modules-load.d/modules.conf
El archivo /etc/modules-load.d/modules.conf es un archivo de configuración que el sistema operativo Debian lee durante el proceso de arranque. Este archivo contiene una lista de los nombres de los módulos del kernel que deben cargarse al inicio. Cada módulo se especifica en una línea separada.
Ejemplo:
...
coretemp
it87
...
El módulo 'coretemp' proporciona la capacidad de monitorear la temperatura de los núcleos del CPU, mientras que 'it87' es un controlador de hardware comúnmente utilizado para monitorear voltajes, temperaturas y velocidades de los ventiladores.
"inline" y "static const" son palabras clave en C++ utilizadas para mejorar la eficiencia y la seguridad del código. "inline" sugiere al compilador reemplazar la llamada a la función en línea con el cuerpo de la función, reduciendo así el costo de llamada a la función. "static const", por otro lado, declara una variable que mantiene su valor entre las invocaciones y no puede ser modificada.
Para compilar código en C++17 en g++, se requiere la opción "-std=c++17". El comando de compilación proporcionado incluye esta opción, junto con otras opciones para la generación de informes de errores y debug, opciones de bibliotecas para Qt, y la especificación de la ubicación de los archivos de cabecera.
A menudo, estas configuraciones de compilación se incluyen en un archivo .pro en proyectos de Qt. Sin embargo, la opción de compilación de C++17 puede no estar habilitada por defecto en algunos sistemas. Para solucionar esto, se pueden agregar las líneas "CONFIG += c++17 console" y "QMAKE_CXXFLAGS += -std=c++17" al archivo .pro. Esto le indica a qmake, el sistema de compilación de Qt, que compile el código usando el estándar C++17, lo que es necesario para el uso de "inline" y "static const" como se prevé en C++17.
No me molesto ha editar ¿a quien vamos a engañar?
QVector::at(int i) const devuelve una referencia constante al elemento
en la posición <i>, no un puntero. No se puede obtener directamente un
puntero al elemento utilizando este método.
El operador de índice
[] devuelve una referencia (no constante) al elemento.Hay que tener en
cuenta que este método no realiza ninguna verificación de rango. Si el
índice está fuera del rango válido del QVector, el comportamiento es
indefinido y puede causar errores en tiempo de ejecución. Es conveniente
verificar el rango antes de devolver el puntero.
MiContainer * at(int idx) { return &_db[idx];} // funciona
MiContainer * at(int idx) { return &_db.at(idx);}// no funciona
error: invalid conversion from ‘const FunctionContainer*’ to ‘FunctionContainer*’ [-fpermissive]
Versión con verificacion de rango:
MiContainer * at(int idx) {
assert(idx>=0 && idx<_db.size(); //verificación de rango durante el desarrollo
return &_db[idx];
}
Respuesta concisa:
cut -d: -f1,3 /etc/passwd
-d: El delimitador de campo es ':'
-f1,3. Interesan los campos 1 y 3.
/etc/passwd guarda todos los usuarios del sistema.
En el cpp:
y a lo hora de compilar:
g++ -o tst01 tst01.cpp -lgmpxx -lgmp
La posibilidad de crear archivos de texto puedan ser leídos en voz alta por una voz artificial, plantea la duda de cual es la relación entre el tamaño de un texto y el tamaño de un archivo de audio generado por una voz artificial.
Una solución gratuita para textos pequeños la ofrece la API de Google para Text-to-Speech.
Se puede utilizar con python con el proyecto gTTS.
Pero ahora que existe una forma de convertir archivos de texto en archivo de audio, sería interesante conocer la relación entre el tamaño del texto y la características del archivo MP3 generado. Como estamos en el siglo XXI y la era de la IA, aquí dejo lo que le pregunté a chatGPT y lo que contestó:
Con estos datos muestra las formulas que permiten calcular tamaño de archivo de audio y duración de audio a partir del tamaño del texto
muestra 1: onda.txt
40.5 kb texto
15.4 mb audio
duración: 1h 07 minutos
muestra 2: pajaro.txt
19.9 kb texto
6.1 mb audio
duración: 26 minutos
muestra 3:ciclope.txt
60.2 kb texto
18.3 mb audio
duración : 1h 20 minutos
Para calcular el tamaño del archivo de audio y la duración del audio a partir del tamaño del texto, primero necesitamos establecer relaciones entre los datos proporcionados. Vamos a utilizar las tres muestras proporcionadas para crear proporciones entre texto, audio y duración:
Muestra 1:
Texto: 40.5 KB
Audio: 15.4 MB
Duración: 1 h 7 min = 67 min
Muestra 2:
Texto: 19.9 KB
Audio: 6.1 MB
Duración: 26 min
Muestra 3:
Texto: 60.2 KB
Audio: 18.3 MB
Duración: 1 h 20 min = 80 min
Proporción entre tamaño del texto y tamaño del archivo de audio:
Para cada muestra, calcularemos la proporción entre el tamaño del texto y el tamaño del archivo de audio.
Muestra 1: (15.4 MB * 1024 KB/MB) / 40.5 KB ≈ 391.11
Muestra 2: (6.1 MB * 1024 KB/MB) / 19.9 KB ≈ 314.57
Muestra 3: (18.3 MB * 1024 KB/MB) / 60.2 KB ≈ 311.96
La proporción no es constante entre las muestras, pero podemos tomar un promedio de las tres proporciones para obtener una relación aproximada:
Promedio de proporciones ≈ (391.11 + 314.57 + 311.96) / 3 ≈ 339.21
Entonces, podemos usar la siguiente fórmula aproximada para calcular el tamaño del archivo de audio a partir del tamaño del texto:
Tamaño del archivo de audio ≈ (Tamaño del texto) * 339.21
Proporción entre tamaño del texto y duración del audio:
Para cada muestra, calcularemos la proporción entre el tamaño del texto y la duración del audio.
Muestra 1: 67 min / 40.5 KB ≈ 1.65 min/KB
Muestra 2: 26 min / 19.9 KB ≈ 1.31 min/KB
Muestra 3: 80 min / 60.2 KB ≈ 1.33 min/KB
De nuevo, la proporción no es constante, pero podemos tomar un promedio de las tres proporciones para obtener una relación aproximada:
Promedio de proporciones ≈ (1.65 + 1.31 + 1.33) / 3 ≈ 1.43 min/KB
Entonces, podemos usar la siguiente fórmula aproximada para calcular la duración del audio a partir del tamaño del texto:
Duración del audio ≈ (Tamaño del texto) * 1.43 min/KB
Recuerda que estas fórmulas son aproximadas y pueden no ser precisas para todos los casos, ya que las proporciones pueden variar dependiendo de la naturaleza de los datos y otros factores como la tasa de bits, frecuencia de muestreo y codificación utilizada.
A esto añado que la sintesis de voz de Google habla muy despacio y no he sido capaz de que hable más rápido. Una posible solución seria acelerar el tempo el archivo con sox.
sox <filein.mp3> <fileout.mp3> tempo 1.33
parece dar buen resultado, pero eso va con gustos y es sólo una idea.
QString txtDlg = QString ("¿Desea eliminar el capítulo %1?").arg(this->spinCap->value());
QString dlgTitle = "Eliminar capítulo";
int result = QMessageBox::question(this,dlgTitle,txtDlg,
QMessageBox::Yes | QMessageBox::No, //botones
QMessageBox::No // Botón predeterminado (en este caso, "no")
);
if (result == QMessageBox::Yes) {
// El usuario ha pulsado "sí"
} else {
// El usuario ha pulsado "no"
}
Las dos maneras de conectar un QAction con un slot:
connect(_actionBorrar, &QAction::triggered, this, &MainWindow::borrarChapter);
&QAction::triggered: Es un puntero a la función miembro triggered de la clase QAction.
&MainWindow::borrarChapter: Es un puntero a la función miembro borrarChapter de la clase MainWindow. borrarChapter es un slot personalizado que contiene el código que se ejecutará cuando se conecte a una señal y esta se emita
Con la nueva sintataxis en la declaracion de la clase los bloques signals: y public slots: son opcionales. Las señales no tienen que estar bajo una etiqueta signals, pero deben ser declaradas como funciones miembro sin implementación.
Ventajas sobre la sintaxis antigua:
Verificación en tiempo de compilación: Si la señal o el slot no existen o no coinciden en sus tipos de argumentos, el compilador generará un error. Esto ayuda a detectar errores antes de que se ejecute el programa.
Mayor legibilidad: Al utilizar punteros a funciones miembro, queda más claro qué función de qué objeto se está conectando.
Soporte para funciones lambda: Con esta sintaxis, puedes conectar una señal directamente a una función lambda en lugar de tener que definir un slot separado.
connect(_actionBorrar, SIGNAL(triggered()), this, SLOT(borrarChapter()));
Desventajas en comparación con la sintaxis tipo-safe:
1. if (saveFilename.isEmpty()) return;
2. if (saveFilename=="") return;
La función "isEmpty()" es una función de la clase QString que verifica si la cadena de texto está vacía o no. Esta función se recomienda para verificar si un QString está vacío.
Por otro lado, la expresión saveFilename=="" es una comparación de cadenas de texto que compara explícitamente el QString con una cadena de texto vacía. Esta comparación también funciona, pero no es la forma recomendada de verificar si un QString está vacío.
La principal diferencia entre ambas expresiones es que la función "isEmpty()" es más eficiente, ya que utiliza una verificación interna de la longitud de la cadena de texto. En cambio, la comparación de cadenas de texto saveFilename=="" realiza una comparación explícita y requiere más tiempo de ejecución.
Además, también es posible que la comparación explícita saveFilename=="" no funcione correctamente en algunas situaciones si el QString contiene caracteres especiales o espacios en blanco. Por lo tanto, en general, es mejor utilizar la función "isEmpty()" para verificar si un QString está vacío.
Guardar el archivo en un subdirectorio del proyecto:
<directorio del proyecto>/recursos/template01.html
Click derecho en el proyecto en la ventana del navegador y seleccionar add new...
En la ventana add new:
Qt - Qt Resource File
En la ventana Qt resource File - Location
name: <El nombre del archivo de recursos> p.j. "templates.qrc" que se ubicará debajo de Resources como Resources/templates.qrc
path: <la del proyecto>
Click derecho sobre templates.qrc. Seleccionar add existing files...
El archivo aparece en templates.qrc/recursos/templat01.html
Acceso al archivo:
QString filename = ":/recursos/template01.html";
Para leer el archivo:
QFile file(filename);
QStringList lstret;
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) assert(false);
while (!file.atEnd()) {
QByteArray line = file.readLine();
process_line(line);
}
Formas de imprimir el contenido de un QStringList
// Recorre la lista y muestra cada elemento
for (int i = 0; i < lista.size(); ++i) {
QString elemento = lista.at(i);
qDebug() << elemento; // Imprime el elemento en la consola
}
for (QString elemento:lstTemplate)
{
qDebug() << Q_FUNC_INFO << elemento;
}
Esta versión tiene la desventaja de que realiza una copia de cada elemento de la lista, lo que puede tener un impacto en el rendimiento si la lista es grande o si se está realizando operaciones costosas en cada elemento.
for (const QString &elemento : lstTemplate) {
qDebug() << Q_FUNC_INFO << elemento;
}
Observaciones:
Al utilizar una referencia constante, se evita la copia de los elementos y se mejora el rendimiento del programa si la lista es grande o si se está realizando operaciones costosas en cada elemento.
En el constructor:
1) Crear una nueva instancia de la clase QToolBar.
QToolBar * secondBar = new QToolBar(this);
2) (opcional) Crear un la QLabel y ponerla en la toolbar, por hacer algo
QLabel *label1 = new QLabel("Label de ejemplo");
secondBar->addWidget(label1);
3) Añadir la toobar a la ventana.
addToolBar(secondBar);Creación de un botón en el toolbar con tres lineas en el contructor:
QAction *action1 = new QAction("Abrir", this);
ui->mainToolBar->addAction(action1);
connect(action1, &QAction::triggered, this, &MainWindow::openFile);
1) QAction *action1 = new QAction("Abrir", this);
Se crea una nueva acción con el nombre "Abrir" y se asigna a la variable action1. El this
pasado como segundo parámetro es un puntero al objeto que está creando
la acción. En este caso, se asume que es la ventana principal (MainWindow) de la aplicación.
2) ui->mainToolBar->addAction(action1);
Se agrega la acción action1 a la barra de herramientas principal (mainToolBar) de la ventana principal (ui).
3) connect(action1, &QAction::triggered, this, &MainWindow::openFile);
Se conecta la señal triggered de la acción action1 con la ranura openFile() en la ventana principal (MainWindow). Cuando se activa la acción, se llamará a la función openFile() en la ventana principal.
Observar que la funcion MainWindow::openfile() se conecta como &MainWindow::openFile. Esto se debe a que connect recibe como parámetro la dirección de la memoria de la función.
Nota: Para acceder a los metodos del qaction fuera del constructor, hay que declararlo en la clase, fuera del constructor.
en mainwindow.h:
QAction *action1;
en el constructor:
action1 = new QAction("Abrir", this);
y en cualquier funcion se utliza:
action1->setEnabled(false);Nota 2: Se puede declarar en el constructor, pero al QAction hay que darle un nombre con setObjectName() y hay que buscarlo con ui->mainToolBar->findChild<QAction*>(<nombre>).Aquí se utiliza una versión antigua de imagemagick
El script:
El resultado:
Más información sobre la clase bytes.