#include "main_window.hpp" #include "config.hpp" #include #include #include #include #include #include #include namespace getsuyomi { using fud::FudStatus; using GetEnvResult = fud::Result; constexpr const char* HOME{"HOME"}; std::optional getEnvVar(const char* envVar); void getEnvVar(const std::string envVar, std::string& envValue, const char* backup); GetEnvResult getEnvironment(); GetsuyomiApp::GetsuyomiApp() : m_getsuyomi{new Getsuyomi()} { readSettings(); } FudStatus GetsuyomiApp::setup() { setCentralWidget(m_getsuyomi); QCoreApplication::setApplicationName(AppName); QCoreApplication::setApplicationVersion(AppVersionString); setWindowTitle(AppName); auto envResult = getEnvironment(); if (envResult.isError()) { return envResult.getError(); } createActions(); createMenus(); createToolBar(); constexpr int minimumWidth = 640; constexpr int minimumHeight = 480; setMinimumSize(minimumWidth, minimumHeight); show(); return FudStatus::Success; } void GetsuyomiApp::createActions() { m_openFile = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::DocumentOpen), tr("&Open File"), this); m_openFile->setShortcuts(QKeySequence::Open); m_openFile->setStatusTip(tr("Open a file")); connect(m_openFile, &QAction::triggered, this, &GetsuyomiApp::openFile); m_openDirectory = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::FolderOpen), tr("Open Directory"), this); m_openDirectory->setShortcut(Qt::CTRL | Qt::ALT | Qt::Key_O); m_openDirectory->setStatusTip(tr("Open a directory")); connect(m_openDirectory, &QAction::triggered, this, &GetsuyomiApp::openDirectory); m_quitAction = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::ApplicationExit), tr("&Quit"), this); m_quitAction->setShortcuts(QKeySequence::Quit); m_quitAction->setStatusTip(tr("Quit")); connect(m_quitAction, &QAction::triggered, this, &GetsuyomiApp::quit); auto nextShortcuts = QList{}; nextShortcuts.append(QKeySequence{Qt::Key_L}); nextShortcuts.append(QKeySequence{Qt::Key_Right}); nextShortcuts.append(QKeySequence{Qt::Key_Down}); m_nextAction = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::GoNext), tr("Next"), this); m_nextAction->setShortcuts(nextShortcuts); m_nextAction->setStatusTip(tr("Next")); connect(m_nextAction, &QAction::triggered, this, &GetsuyomiApp::next); auto backShortcuts = QList{}; backShortcuts.append(QKeySequence{Qt::Key_H}); backShortcuts.append(QKeySequence{Qt::Key_Left}); backShortcuts.append(QKeySequence{Qt::Key_Up}); m_backAction = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::GoPrevious), tr("Back"), this); m_backAction->setShortcuts(backShortcuts); m_backAction->setStatusTip(tr("Back")); connect(m_backAction, &QAction::triggered, this, &GetsuyomiApp::back); } void GetsuyomiApp::createMenus() { m_menuBar = menuBar()->addMenu(tr("&File")); m_menuBar->addAction(m_openFile); m_menuBar->addAction(m_openDirectory); m_menuBar->addAction(m_quitAction); } void GetsuyomiApp::createToolBar() { m_toolBar = addToolBar(tr("&Navigation")); m_toolBar->addAction(m_backAction); m_toolBar->addAction(m_nextAction); } void GetsuyomiApp::openFile() { auto dialog = QFileDialog( this, tr("Open Archive"), m_lastOpenedDirectory, tr("Archive types (*.zip *.cbz *.cbr *.gz)")); dialog.setFileMode(QFileDialog::ExistingFile); QString filename; if (dialog.exec()) { auto filenames = dialog.selectedFiles(); if (filenames.length() == 0) { qWarning("No files selected."); return; } else if (filenames.length() > 1) { qWarning("Too many files selected %llu.", filenames.length()); return; } filename = filenames[0]; m_lastOpenedDirectory = dialog.directory().absolutePath(); qDebug("Last opened directory is %s", qPrintable(m_lastOpenedDirectory)); } else { qWarning("File dialog did not execute"); return; } if (filename.endsWith(".zip")) { auto* archive = new ZipArchive(filename); if (!archive->valid()) { qCritical("Failed to change archive"); } else { m_getsuyomi->setArchive(archive); } } else { qCritical("Unsupported file extension"); } } void GetsuyomiApp::openDirectory() { auto dialog = QFileDialog( this, tr("Open Directory"), m_lastOpenedDirectory); dialog.setFileMode(QFileDialog::Directory); QString directoryName; if (dialog.exec()) { auto filenames = dialog.selectedFiles(); if (filenames.length() == 0) { qWarning("No files selected."); return; } else if (filenames.length() > 1) { qWarning("Too many files selected %llu.", filenames.length()); return; } directoryName = filenames[0]; m_lastOpenedDirectory = dialog.directory().absolutePath(); } else { qWarning("File dialog did not execute"); return; } qDebug("Opened directory %s", qPrintable(directoryName)); } void GetsuyomiApp::quit() { QCoreApplication::quit(); } void GetsuyomiApp::next() { qDebug("Next"); m_getsuyomi->next(); } void GetsuyomiApp::back() { qDebug("Back"); m_getsuyomi->back(); } void GetsuyomiApp::closeEvent(QCloseEvent* event) { writeSettings(); QMainWindow::closeEvent(event); } void GetsuyomiApp::readSettings() { QSettings settings{AppVendor, AppName}; restoreGeometry(settings.value("geometry").toByteArray()); restoreState(settings.value("windowState").toByteArray()); m_lastOpenedDirectory = settings.value("lastOpenedDirectory", QDir::homePath()).toString(); qDebug("ReadSettings - last directory is %s", qPrintable(m_lastOpenedDirectory)); } void GetsuyomiApp::writeSettings() { QSettings settings{AppVendor, AppName}; settings.setValue("geometry", saveGeometry()); settings.setValue("windowState", saveState()); settings.setValue("lastOpenedDirectory", m_lastOpenedDirectory); settings.sync(); qDebug() << "Called writeSettings, last dir is " << settings.value("lastOpenedDirectory"); } std::optional getEnvVar(const char* envVar) { const QByteArray defaultArray{}; if (envVar == nullptr) { return std::nullopt; } QByteArray varArray = qgetenv(envVar); if (varArray == defaultArray) { return std::nullopt; } return varArray.toStdString(); } void getEnvVar(const std::string envVar, std::string& envValue, const char* backup) { auto envValueOpt = getEnvVar(envVar.c_str()); if (envValueOpt == std::nullopt || envValueOpt->length() == 0) { std::filesystem::path envValuePath{HOME}; envValuePath.append(backup); envValue = envValuePath; } else { envValue = *envValueOpt; } qDebug("%s is %s", envVar.c_str(), envValue.c_str()); } GetEnvResult getEnvironment() { GetsuyomiConfig config{}; auto homeOpt = getEnvVar(HOME); if (homeOpt == std::nullopt || homeOpt->length() == 0) { qCritical("Error getting home"); return GetEnvResult::error(FudStatus::Failure); } config.home = *homeOpt; qDebug("Home is %s", config.home.c_str()); /* If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used. */ const std::string XdgDataHome{"XDG_DATA_HOME"}; getEnvVar(XdgDataHome, config.dataHome, ".local/share"); /* If $XDG_CONFIG_HOME is either not set or empty, a default equal to $HOME/.config should be used. */ const std::string XdgConfigHome{"XDG_CONFIG_HOME"}; getEnvVar(XdgConfigHome, config.configHome, ".config"); /* If $XDG_STATE_HOME is either not set or empty, a default equal to $HOME/.local/state should be used. */ const std::string XdgStateHome{"XDG_STATE_HOME"}; getEnvVar(XdgStateHome, config.stateHome, ".local/state"); return GetEnvResult::okay(config); } } // namespace getsuyomi