Skip to content

Commit

Permalink
Fix Github Issue #9: Show list of recent files
Browse files Browse the repository at this point in the history
  • Loading branch information
juzzlin committed Jan 27, 2020
1 parent fa8af84 commit 9895241
Show file tree
Hide file tree
Showing 17 changed files with 685 additions and 174 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ x.y.z
=====

New features:

* Fix Github Issue #9: Show list of recent files

Bug fixes:

Expand Down
4 changes: 4 additions & 0 deletions heimer.pro
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ HEADERS += \
$$SRC/node_base.hpp \
$$SRC/node_handle.hpp \
$$SRC/reader.hpp \
$$SRC/recent_files_manager.hpp \
$$SRC/recent_files_menu.hpp \
$$SRC/selection_group.hpp \
$$SRC/serializer.hpp \
$$SRC/state_machine.hpp \
Expand Down Expand Up @@ -92,6 +94,8 @@ SOURCES += \
$$SRC/node_base.cpp \
$$SRC/node_handle.cpp \
$$SRC/reader.cpp \
$$SRC/recent_files_manager.cpp \
$$SRC/recent_files_menu.cpp \
$$SRC/selection_group.cpp \
$$SRC/serializer.cpp \
$$SRC/state_machine.cpp \
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ set(SRC
node_base.cpp
node_handle.cpp
reader.cpp
recent_files_manager.cpp
recent_files_menu.cpp
selection_group.cpp
serializer.cpp
state_machine.cpp
Expand Down
6 changes: 5 additions & 1 deletion src/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "main_window.hpp"
#include "mediator.hpp"
#include "png_export_dialog.hpp"
#include "recent_files_manager.hpp"
#include "state_machine.hpp"
#include "user_exception.hpp"

Expand Down Expand Up @@ -183,7 +184,10 @@ void Application::runState(StateMachine::State state)
case StateMachine::State::InitializeNewMindMap:
m_mediator->initializeNewMindMap();
break;
case StateMachine::State::SaveMindMap:
case StateMachine::State::OpenRecent:
doOpenMindMap(RecentFilesManager::instance().selectedFile());
break;
case StateMachine::State::Save:
saveMindMap();
break;
case StateMachine::State::ShowBackgroundColorDialog:
Expand Down
10 changes: 10 additions & 0 deletions src/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ static const QColor TEXT_EDIT_BACKGROUND_COLOR { 0x00, 0x00, 0x00, 0x10 };

} // namespace Node

namespace RecentFiles {

static const int MAX_FILES = 8;

static const QString QSETTINGS_ARRAY_KEY = "recentFilesArray";

static const QString QSETTINGS_FILE_PATH_KEY = "filePath";

} // namespace RecentFiles

namespace Scene {

static const QColor BARRIER_COLOR { 255, 0, 0, 128 };
Expand Down
3 changes: 3 additions & 0 deletions src/editor_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "constants.hpp"
#include "node.hpp"
#include "reader.hpp"
#include "recent_files_manager.hpp"
#include "selection_group.hpp"
#include "serializer.hpp"
#include "writer.hpp"
Expand Down Expand Up @@ -66,6 +67,7 @@ void EditorData::loadMindMapData(QString fileName)
#endif
m_fileName = fileName;
setIsModified(false);
RecentFilesManager::instance().addRecentFile(fileName);

m_undoStack.clear();
}
Expand Down Expand Up @@ -155,6 +157,7 @@ bool EditorData::saveMindMapAs(QString fileName)
if (Writer::writeToFile(Serializer::toXml(*m_mindMapData), fileName)) {
m_fileName = fileName;
setIsModified(false);
RecentFilesManager::instance().addRecentFile(fileName);
return true;
}

Expand Down
11 changes: 11 additions & 0 deletions src/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "about_dlg.hpp"
#include "constants.hpp"
#include "mediator.hpp"
#include "recent_files_manager.hpp"
#include "recent_files_menu.hpp"
#include "simple_logger.hpp"
#include "whats_new_dlg.hpp"

Expand Down Expand Up @@ -239,6 +241,14 @@ void MainWindow::createFileMenu()
emit actionTriggered(StateMachine::Action::OpenSelected);
});

// Add "Recent Files"-menu
const auto recentFilesMenu = new RecentFilesMenu;
const auto recentFilesMenuAction = fileMenu->addMenu(recentFilesMenu);
recentFilesMenuAction->setText(tr("Recent &Files"));
connect(recentFilesMenu, &RecentFilesMenu::fileSelected, [=]() {
emit actionTriggered(StateMachine::Action::RecentFileSelected);
});

fileMenu->addSeparator();

// Add "save"-action
Expand Down Expand Up @@ -281,6 +291,7 @@ void MainWindow::createFileMenu()

connect(fileMenu, &QMenu::aboutToShow, [=]() {
exportToPNGAction->setEnabled(m_mediator->hasNodes());
recentFilesMenuAction->setEnabled(RecentFilesManager::instance().hasRecentFiles());
});
}

Expand Down
92 changes: 92 additions & 0 deletions src/recent_files_manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// This file is part of Heimer.
// Copyright (C) 2020 Jussi Lind <jussi.lind@iki.fi>
//
// Heimer is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Heimer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Heimer. If not, see <http://www.gnu.org/licenses/>.

#include "recent_files_manager.hpp"
#include "constants.hpp"
#include "contrib/SimpleLogger/src/simple_logger.hpp"

#include <stdexcept>

#include <QSettings>

std::unique_ptr<RecentFilesManager> RecentFilesManager::m_instance;

RecentFilesManager::RecentFilesManager()
{
if (RecentFilesManager::m_instance) {
throw std::runtime_error("RecentFilesManager already instantiated!");
}

QSettings settings;
const int size = settings.beginReadArray(Constants::RecentFiles::QSETTINGS_ARRAY_KEY);
for (int i = 0; i < size; i++) {
settings.setArrayIndex(i);
m_recentFiles.push_back(settings.value(Constants::RecentFiles::QSETTINGS_FILE_PATH_KEY).toString());
}
settings.endArray();
}

RecentFilesManager & RecentFilesManager::instance()
{
if (!RecentFilesManager::m_instance) {
RecentFilesManager::m_instance.reset(new RecentFilesManager);
juzzlin::L().debug() << "RecentFilesManager created";
}

return *RecentFilesManager::m_instance;
}

void RecentFilesManager::addRecentFile(QString filePath)
{
m_recentFiles.removeAll(filePath);
m_recentFiles.push_front(filePath);

while (m_recentFiles.size() > Constants::RecentFiles::MAX_FILES) {
m_recentFiles.pop_back();
}

juzzlin::L().debug() << "Added recent file: " << filePath.toStdString();
juzzlin::L().debug() << "Recent file count: " << m_recentFiles.size();

QSettings settings;
settings.beginWriteArray(Constants::RecentFiles::QSETTINGS_ARRAY_KEY);
for (int i = 0; i < m_recentFiles.size(); i++) {
settings.setArrayIndex(i);
settings.setValue(Constants::RecentFiles::QSETTINGS_FILE_PATH_KEY, m_recentFiles.at(i));
}
settings.endArray();
}

const QList<QString> & RecentFilesManager::getRecentFiles() const
{
return m_recentFiles;
}

bool RecentFilesManager::hasRecentFiles() const
{
return !m_recentFiles.empty();
}

void RecentFilesManager::setSelectedFile(QString selectedFile)
{
juzzlin::L().debug() << "Recent file selected: " << selectedFile.toStdString();

m_selectedFile = selectedFile;
}

QString RecentFilesManager::selectedFile() const
{
return m_selectedFile;
}
51 changes: 51 additions & 0 deletions src/recent_files_manager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// This file is part of Heimer.
// Copyright (C) 2020 Jussi Lind <jussi.lind@iki.fi>
//
// Heimer is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Heimer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Heimer. If not, see <http://www.gnu.org/licenses/>.

#ifndef RECENT_FILES_MANAGER_HPP
#define RECENT_FILES_MANAGER_HPP

#include <QList>
#include <QObject>
#include <QString>

#include <memory>

class RecentFilesManager : public QObject
{
public:
RecentFilesManager();

static RecentFilesManager & instance();

const QList<QString> & getRecentFiles() const;

bool hasRecentFiles() const;

QString selectedFile() const;

public slots:
void addRecentFile(QString filePath);

void setSelectedFile(QString filePath);

private:
static std::unique_ptr<RecentFilesManager> m_instance;

QList<QString> m_recentFiles;

QString m_selectedFile;
};

#endif // RECENT_FILES_MANAGER_HPP
39 changes: 39 additions & 0 deletions src/recent_files_menu.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// This file is part of Heimer.
// Copyright (C) 2020 Jussi Lind <jussi.lind@iki.fi>
//
// Heimer is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Heimer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Heimer. If not, see <http://www.gnu.org/licenses/>.

#include "recent_files_menu.hpp"
#include "recent_files_manager.hpp"

#include <functional>

RecentFilesMenu::RecentFilesMenu(QWidget * parent)
: QMenu(parent)
{
connect(this, &QMenu::aboutToShow, [this]() {
for (auto && action : actions()) {
removeAction(action);
}
// clang-format off
for (auto && filePath : RecentFilesManager::instance().getRecentFiles()) {
const auto action = addAction(filePath);
const auto handler = std::bind([this](QString filePath) {
RecentFilesManager::instance().setSelectedFile(filePath);
this->fileSelected(filePath);
}, action->text());
connect(action, &QAction::triggered, handler);
}
// clang-format on
});
}
42 changes: 42 additions & 0 deletions src/recent_files_menu.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// This file is part of Heimer.
// Copyright (C) 2020 Jussi Lind <jussi.lind@iki.fi>
//
// Heimer is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Heimer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Heimer. If not, see <http://www.gnu.org/licenses/>.

#ifndef RECENT_FILES_MENU_HPP
#define RECENT_FILES_MENU_HPP

#include <QMenu>
#include <QString>

#include <list>

class QAction;

class RecentFilesMenu : public QMenu
{
Q_OBJECT

public:
explicit RecentFilesMenu(QWidget * parent = nullptr);

signals:
void fileSelected(QString filePath);

private:
std::list<QAction *> m_actions;

QString m_selectedFile;
};

#endif // RECENT_FILES_MENU_HPP
16 changes: 14 additions & 2 deletions src/state_machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ void StateMachine::calculateState(StateMachine::Action action)
case QuitType::Open:
m_state = State::ShowOpenDialog;
break;
case QuitType::OpenRecent:
m_state = State::OpenRecent;
break;
default:
m_state = State::Edit;
break;
Expand Down Expand Up @@ -111,7 +114,7 @@ void StateMachine::calculateState(StateMachine::Action action)
case Action::NotSavedDialogAccepted:
case Action::SaveSelected:
if (m_mediator->canBeSaved()) {
m_state = State::SaveMindMap;
m_state = State::Save;
} else {
m_state = State::ShowSaveAsDialog;
}
Expand All @@ -121,9 +124,18 @@ void StateMachine::calculateState(StateMachine::Action action)
m_state = State::ShowSaveAsDialog;
break;

case Action::RecentFileSelected:
m_quitType = QuitType::OpenRecent;
if (m_mediator->isModified()) {
m_state = State::ShowNotSavedDialog;
} else {
m_state = State::OpenRecent;
}
break;

default:
juzzlin::L().warning() << "Action " << static_cast<int>(action) << " not handled!";
};
}

emit stateChanged(m_state);
}
Expand Down
Loading

0 comments on commit 9895241

Please sign in to comment.