src/libraries.cpp

Sun, 03 Nov 2019 18:09:47 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Sun, 03 Nov 2019 18:09:47 +0200
changeset 13
6e838748867b
parent 12
fe67489523b5
child 22
6da867fa5429
permissions
-rw-r--r--

renamings

#include <QSettings>
#include "libraries.h"

/**
 * @brief Constructs a new library manager
 * @param parent Parent object
 */
LibraryManager::LibraryManager(QObject* parent):
	QAbstractTableModel{parent}
{
}

/**
 * @brief Constructs a library manager from settings
 * @param settings Settings to construct from
 * @param parent Parent object
 */
LibraryManager::LibraryManager(QSettings* settings, QObject* parent) :
	QAbstractTableModel{parent}
{
	this->restoreFromSettings(settings);
}

/**
 * @brief Yields a begin-terator for the libraries
 * @return iterator
 */
QVector<Library>::const_iterator LibraryManager::begin() const
{
	return this->libraries.begin();
}

/**
 * @brief Yields an end-iterator for the libraries
 * @return iterator
 */
QVector<Library>::const_iterator LibraryManager::end() const
{
	return this->libraries.end();
}

/**
 * @brief Searches the libraries for the specified file name.
 * @param fileName File to search for
 * @return Full path to the file, or empty string if not found.
 */
QString LibraryManager::findFile(QString fileName) const
{
	QString path;
	fileName.replace("\\", "/");
	bool found = false;
	for (const Library& library : this->libraries)
	{
		for (const QString& subdirectory : {"parts", "p"})
		{
			QDir directory = library.path;
			directory.cd(subdirectory);
			QFileInfo fileInfo = directory.absoluteFilePath(fileName);
			if (fileInfo.exists() && fileInfo.isFile())
			{
				path = fileInfo.absoluteFilePath();
				found = true;
				break;
			}
		}
		if (found)
		{
			break;
		}
	}
	return path;
}

/**
 * @brief Adds a new library to the end of the libraries list.
 * @param library Library to add
 */
void LibraryManager::addLibrary(const Library& library)
{
	emit layoutAboutToBeChanged();
	libraries.append(library);
	emit layoutChanged();
}

/**
 * @brief Removes a library by index. Does nothing if the index is not valid.
 * @param libraryIndex Index of the library
 */
void LibraryManager::removeLibrary(const int libraryIndex)
{
	Q_ASSERT(isValidIndex(libraryIndex));
	if (isValidIndex(libraryIndex))
	{
		emit layoutAboutToBeChanged();
		libraries.remove(libraryIndex);
		emit layoutChanged();
	}
}

/**
 * @brief Gets a library by index.
 * @warning Index is assumed to be valid.
 * @param libraryIndex Index of the library
 * @return const reference
 */
const Library& LibraryManager::library(int libraryIndex) const
{
	Q_ASSERT(isValidIndex(libraryIndex));
	return this->libraries[libraryIndex];
}

/**
 * @brief Changes the path of the specified library
 * @param libraryIndex Index of the library
 * @param path New path
 */
void LibraryManager::setLibraryPath(int libraryIndex, const QDir& path)
{
	if (this->isValidIndex(libraryIndex))
	{
		this->libraries[libraryIndex].path = path;
		this->signalLibraryChange(libraryIndex);
	}
}

/**
 * @brief Changes the role of the specified library
 * @param libraryIndex Index of the library
 * @param role New role
 */
void LibraryManager::setLibraryRole(int libraryIndex, const Library::Role role)
{
	if (this->isValidIndex(libraryIndex))
	{
		this->libraries[libraryIndex].role = role;
		this->signalLibraryChange(libraryIndex);
	}
}

/**
 * @brief Restores the libraries from the specified settings object. All unsaved
 * changes are lost.
 * @param settings Settings object to restore from.
 */
void LibraryManager::restoreFromSettings(QSettings* settings)
{
	this->libraries = settings->value("libraries").value<Libraries>();
}

/**
 * @brief Saves the libraries to the specified settings object.
 * @param settings Settings object to modify.
 */
void LibraryManager::storeToSettings(QSettings* settings)
{
	QVariant librariesValue = QVariant::fromValue(this->libraries);
	settings->setValue("libraries", librariesValue);
}

/**
 * @returns the amount of libraries
 */
int LibraryManager::count() const
{
	return this->libraries.size();
}

void LibraryManager::moveLibrary(const int libraryFromIndex, const int libraryToIndex)
{
	if (isValidIndex(libraryFromIndex) and
		(isValidIndex(libraryToIndex) or libraryToIndex == count()) and
		libraryFromIndex != libraryToIndex)
	{
		emit layoutAboutToBeChanged();
		const Library library = this->library(libraryFromIndex);
		if (libraryToIndex > libraryFromIndex)
		{
			this->libraries.insert(libraryToIndex, library);
			this->libraries.removeAt(libraryFromIndex);
		}
		else if (libraryToIndex < libraryFromIndex)
		{
			this->libraries.removeAt(libraryFromIndex);
			this->libraries.insert(libraryToIndex, library);
		}
		emit layoutChanged();
	}
}

/**
 * @brief Checks whether the specified index points to a valid library.
 * @param libraryIndex Index to check
 * @returns whether or not it is valid
 */
bool LibraryManager::isValidIndex(const int libraryIndex) const
{
	return libraryIndex >= 0 && libraryIndex < this->libraries.size();
}

/**
 * @brief Gets a human-readable string for the specified role
 * @param role Role to get a string for
 * @returns string
 */
QString Library::libraryRoleName(const Role role)
{
	switch (role)
	{
	case Library::OfficialLibrary:
		return LibraryManager::tr("Official library");
	case Library::UnofficialLibrary:
		return LibraryManager::tr("Unofficial library");
	case Library::WorkingLibrary:
		return LibraryManager::tr("Working library");
	default:
		return "???";
	}
}

/**
 * @brief Overload necessary to implement QAbstractTableModel
 * @param index
 * @return Item flags
 */
Qt::ItemFlags LibraryManager::flags(const QModelIndex& index) const
{
	Q_UNUSED(index);
	return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

/**
 * @brief Returns data needed to represent the libraries in a table. This function
 * decides how data is represented in a table view.
 * @param index Index to get data for
 * @param role Role of the data (role as in Qt model-view role, not LDraw library role)
 * @returns variant
 */
QVariant LibraryManager::data(const QModelIndex& index, int role) const
{
	if (role != Qt::DisplayRole)
	{
		return {};
	}
	else
	{
		const int row = index.row();
		const Column column = static_cast<Column>(index.column());
		const Library& library = this->library(row);
		switch (column)
		{
		case RoleColumn:
			return Library::libraryRoleName(library.role);
		case PathColumn:
			return library.path.absolutePath();
		}
		return {};
	}
}

/**
 * @brief Returns header texts for a table view. We only implement column headers here.
 * @param section Index of the column (can also be a row but we only have column headers)
 * @param orientation Orientation (we only support horizontal orientation)
 * @param role Role of the data (role as in Qt model-view role, not LDraw library role)
 * @returns variant
 */
QVariant LibraryManager::headerData(int section, Qt::Orientation orientation, int role) const
{
	if (orientation == Qt::Horizontal and role == Qt::DisplayRole)
	{
		switch(static_cast<Column>(section))
		{
		case PathColumn:
			return tr("Path");
		case RoleColumn:
			return tr("Role");
		}
		return {};
	}
	else
	{
		return {};
	}
}

/**
 * @brief Overload necessary to implement QAbstractTableModel.
 * @returns how many rows there are in the table. Since there is one row per library, this returns
 * the amount of libraries.
 */
int LibraryManager::rowCount(const QModelIndex&) const
{
	return this->count();
}

/**
 * @brief LibraryManager::columnCount
 * @returns how many columns there are in the table.
 */
int LibraryManager::columnCount(const QModelIndex&) const
{
	return 2;
}

/**
 * @brief Signals view objects that the specified library has changed. This is necessary
 * to update the table widget know when libraries are changed.
 * @param libraryIndex Index of the library.
 */
void LibraryManager::signalLibraryChange(int libraryIndex)
{
	Q_ASSERT(isValidIndex(libraryIndex));
	const QModelIndex topLeft = this->index(libraryIndex, 0);
	const QModelIndex bottomRight = this->index(libraryIndex, columnCount({}) - 1);
	emit dataChanged(topLeft, bottomRight);
}

/**
 * @brief Overload for operator<< to allow serializing a library into the configuration file.
 * @param stream Stream to write the library into
 * @param library Library to write into the stream
 * @returns the stream
 */
QDataStream& operator<<(QDataStream& stream, const Library& library)
{
	const QString path = library.path.absolutePath();
	const int role = static_cast<int>(library.role);
	return stream << path << role;
}

/**
 * @brief Overload for operator>> to allow serializing a library into the configuration file.
 * @param stream Stream to read the library from
 * @param library Library to obtain from the stream
 * @returns the stream
 */
QDataStream& operator>>(QDataStream& stream, Library& library)
{
	QString path;
	int role;
	QDataStream& result = stream >> path >> role;
	library.path = path;
	library.role = static_cast<Library::Role>(role);
	return result;
}

mercurial