Files
tenmon/mainwindow.cpp
T
2019-09-01 16:04:45 +02:00

255 lines
6.8 KiB
C++

#include "mainwindow.h"
#include <QScrollArea>
#include <QDir>
#include <QKeyEvent>
#include <QMenu>
#include <QMenuBar>
#include <QFileDialog>
#include <QStandardPaths>
#include <QMessageBox>
#include <QProgressDialog>
#include <QDebug>
#include <sys/ioctl.h>
#include <linux/btrfs.h>
#include <QDockWidget>
#include <signal.h>
#include <unistd.h>
#include <sys/socket.h>
int MainWindow::socketPair[2] = {0, 0};
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
loading(false),
queued(0)
{
qRegisterMetaType<ImageInfoData>("ImageInfoData");
m_info = new ImageInfo(this);
QDockWidget *infoDock = new QDockWidget(tr("Image info"), this);
infoDock->setWidget(m_info);
addDockWidget(Qt::LeftDockWidgetArea, infoDock);
m_image = new ImageScrollArea(this);
setCentralWidget(m_image);
resize(800, 600);
setWindowTitle(tr("Image Selector"));
m_ringList = new ImageRingList(this);
connect(m_ringList, SIGNAL(pixmapLoaded(QPixmap)), this, SLOT(pixmapLoaded(QPixmap)));
connect(m_ringList, SIGNAL(currentImageChanged()), this, SLOT(updateWindowTitle()));
connect(m_ringList, SIGNAL(infoLoaded(ImageInfoData)), m_info, SLOT(setInfo(ImageInfoData)));
QMenu *fileMenu = new QMenu(tr("File"), this);
fileMenu->addAction(tr("Open"), this, SLOT(openFile()), QKeySequence("Ctrl+O"));
fileMenu->addAction(tr("Copy marked files"), this, SLOT(copyMarked()));
QAction *liveModeAction = fileMenu->addAction(tr("Live mode"), this, SLOT(liveMode(bool)));
liveModeAction->setCheckable(true);
fileMenu->addAction(tr("Exit"), this, SLOT(close()));
menuBar()->addMenu(fileMenu);
QMenu *viewMenu = new QMenu(tr("View"), this);
viewMenu->addAction(tr("Zoom In"), m_image, SLOT(zoomIn()), QKeySequence::ZoomIn);
viewMenu->addAction(tr("Zoom Out"), m_image, SLOT(zoomOut()), QKeySequence::ZoomOut);
viewMenu->addAction(tr("Best Fit"), m_image, SLOT(bestFit()), QKeySequence("Ctrl+1"));
viewMenu->addAction(tr("100%"), m_image, SLOT(oneToOne()));
menuBar()->addMenu(viewMenu);
QMenu *selectMenu = new QMenu(tr("Select"), this);
selectMenu->addAction(tr("Mark"), this, SLOT(markImage()), Qt::Key_F5);
selectMenu->addAction(tr("Unmark"), this, SLOT(unmarkImage()), Qt::Key_F8);
selectMenu->addSeparator();
selectMenu->addAction(tr("Mark and next"), this, SLOT(markAndNext()), Qt::Key_M);
selectMenu->addAction(tr("Unmark and next"), this, SLOT(unmarkAndNext()), Qt::Key_X);
menuBar()->addMenu(selectMenu);
m_database = new Database(this);
if(!m_database->init())
QMessageBox::critical(this, tr("Can't open DB"), tr("Can't open SQLITE database"));
setupSigterm();
}
MainWindow::~MainWindow()
{
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if(!loading)
{
switch (event->key())
{
case Qt::Key_Left:
m_ringList->decrement();
break;
case Qt::Key_Right:
m_ringList->increment();
break;
default:
event->ignore();
break;
}
}
else
{
event->ignore();
}
if(event->isAccepted())
updateWindowTitle();
}
void MainWindow::keyReleaseEvent(QKeyEvent *event)
{
event->ignore();
}
void MainWindow::setupSigterm()
{
struct sigaction signal;
signal.sa_handler = MainWindow::signalHandler;
sigemptyset(&signal.sa_mask);
signal.sa_flags = 0;
signal.sa_flags |= SA_RESTART;
sigaction(SIGHUP, &signal, 0);
sigaction(SIGTERM, &signal, 0);
sigaction(SIGINT, &signal, 0);
::socketpair(AF_UNIX, SOCK_STREAM, 0, socketPair);
socketNotifier = new QSocketNotifier(socketPair[1], QSocketNotifier::Read, this);
connect(socketNotifier, SIGNAL(activated(int)), this, SLOT(socketNotify()));
}
void MainWindow::signalHandler(int)
{
char a = 1;
::write(socketPair[0], &a, sizeof(a));
}
void MainWindow::socketNotify()
{
socketNotifier->setEnabled(false);
char tmp;
read(socketPair[1], &tmp, sizeof(tmp));
close();
socketNotifier->setEnabled(true);
}
void MainWindow::pixmapLoaded(QPixmap pix)
{
m_image->setImage(pix);
}
void MainWindow::openFile()
{
QStringList standardLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
QString path;
if(standardLocations.size())
path = standardLocations.first();
QString file = QFileDialog::getOpenFileName(this, tr("Open file"), path, tr("Images (*.jpg *.png *.cr2 *.JPG *.PNG *.CR2)"));
if(!file.isEmpty())
{
QFileInfo info(file);
m_ringList->setFile(info.canonicalFilePath());
updateWindowTitle();
}
}
void MainWindow::markImage()
{
ImagePtr ptr = m_ringList->currentImage();
if(ptr)
{
QString file = ptr->name();
if(!file.isEmpty())
m_database->mark(file);
updateWindowTitle();
}
}
void MainWindow::unmarkImage()
{
ImagePtr ptr = m_ringList->currentImage();
if(ptr)
{
QString file = ptr->name();
if(!file.isEmpty())
m_database->unmark(file);
updateWindowTitle();
}
}
void MainWindow::markAndNext()
{
markImage();
m_ringList->increment();
updateWindowTitle();
}
void MainWindow::unmarkAndNext()
{
unmarkImage();
m_ringList->increment();
updateWindowTitle();
}
void MainWindow::copyMarked()
{
QString dest = QFileDialog::getExistingDirectory(this, tr("Select destination"));
QDir dir(dest);
if(!dest.isEmpty() && dir.exists())
{
int i = 0;
QStringList files = m_database->getMarkedFiles();
QProgressDialog progress(tr("Copying"), tr("Cancel"), 0, files.size(), this);
progress.setWindowModality(Qt::WindowModal);
progress.show();
foreach(const QString &file, files)
{
QFileInfo info(file);
QFile srcFile(file);
QFile dstFile(dir.absoluteFilePath(info.fileName()));
if(dstFile.exists())
continue;
if(progress.wasCanceled())
break;
srcFile.open(QIODevice::ReadOnly);
dstFile.open(QIODevice::WriteOnly);
if(ioctl(dstFile.handle(), BTRFS_IOC_CLONE, srcFile.handle()) < 0)
{
dstFile.remove();
dstFile.close();
qDebug() << dstFile.fileName();
srcFile.copy(dstFile.fileName());
}
progress.setValue(i++);
}
}
}
void MainWindow::liveMode(bool active)
{
m_ringList->setLiveMode(active);
}
void MainWindow::updateWindowTitle()
{
ImagePtr ptr = m_ringList->currentImage();
if(ptr)
{
QFileInfo info(ptr->name());
QString title = info.fileName();
if(m_database->isMarked(ptr->name()))
title += " *";
setWindowTitle(title);
}
}