Files
lmms/include/FileBrowser.h
2025-11-11 12:57:14 -05:00

310 lines
7.5 KiB
C++

/*
* FileBrowser.h - include file for FileBrowser
*
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - https://lmms.io
*
* This program 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 2 of the License, or (at your option) any later version.
*
* This program 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 this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef LMMS_GUI_FILE_BROWSER_H
#define LMMS_GUI_FILE_BROWSER_H
#include <QDir>
#include <QMutex>
#include "FileSearchJob.h"
#include "embed.h"
#include <QTreeWidget>
#include "SideBarWidget.h"
#include "lmmsconfig.h"
class QCheckBox;
class QLineEdit;
class QProgressBar;
namespace lmms
{
class InstrumentTrack;
class PlayHandle;
class TrackContainer;
namespace gui
{
class FileBrowserTreeWidget;
class FileItem;
class FileSearchJob;
class FileBrowser : public SideBarWidget
{
Q_OBJECT
public:
enum class Type
{
Normal,
Favorites
};
/**
Create a file browser side bar widget
@param directories '*'-separated list of directories to search for.
If a directory of factory files should be in the list it
must be the last one (for the factory files delimiter to work)
@param filter Filter as used in QDir::match
@param recurse *to be documented*
*/
FileBrowser(Type type, const QString& directories, const QString& filter, const QString& title, const QPixmap& pm,
QWidget* parent, bool dirs_as_items = false, const QString& userDir = "", const QString& factoryDir = "");
~FileBrowser() override = default;
static QDir::Filters dirFilters() { return QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden; }
static QDir::SortFlags sortFlags() { return QDir::LocaleAware | QDir::DirsFirst | QDir::Name | QDir::IgnoreCase; }
private slots:
void reloadTree();
void expandItems(const QList<QString>& expandedDirs, QTreeWidgetItem* item = nullptr);
void giveFocusToFilter();
private:
void keyPressEvent( QKeyEvent * ke ) override;
void addItems(const QString & path);
void saveDirectoriesStates();
void restoreDirectoriesStates();
void onSearch(const QString& filter);
void onSearchMatch(const QString& path);
void onSearchStarted();
void onSearchFinished();
void addContentCheckBox();
FileBrowserTreeWidget * m_fileBrowserTreeWidget;
FileBrowserTreeWidget * m_searchTreeWidget;
QLineEdit * m_filterEdit;
Type m_type;
QProgressBar* m_searchIndicator = nullptr;
FileSearchJob m_searchJob;
QString m_directories; //!< Directories to search, split with '*'
QString m_filter; //!< Filter as used in QDir::match()
bool m_dirsAsItems;
QCheckBox* m_showUserContent = nullptr;
QCheckBox* m_showFactoryContent = nullptr;
QCheckBox* m_showHiddenContent = nullptr;
QBoxLayout *filterWidgetLayout = nullptr;
QBoxLayout *hiddenWidgetLayout = nullptr;
QBoxLayout *outerLayout = nullptr;
QString m_userDir;
QString m_factoryDir;
QList<QString> m_savedExpandedDirs;
QString m_previousFilterValue;
} ;
class FileBrowserTreeWidget : public QTreeWidget
{
Q_OBJECT
public:
FileBrowserTreeWidget( QWidget * parent );
~FileBrowserTreeWidget() override = default;
//! This method returns a QList with paths (QString's) of all directories
//! that are expanded in the tree.
QList<QString> expandedDirs( QTreeWidgetItem * item = nullptr ) const;
protected:
void contextMenuEvent( QContextMenuEvent * e ) override;
void mousePressEvent( QMouseEvent * me ) override;
void mouseMoveEvent( QMouseEvent * me ) override;
void mouseReleaseEvent( QMouseEvent * me ) override;
void keyPressEvent( QKeyEvent * ke ) override;
void keyReleaseEvent( QKeyEvent * ke ) override;
void hideEvent( QHideEvent * he ) override;
void focusOutEvent( QFocusEvent * fe ) override;
private:
//! Start a preview of a file item
void previewFileItem(FileItem* file);
//! If a preview is playing, stop it.
void stopPreview();
void handleFile( FileItem * fi, InstrumentTrack * it );
void openInNewInstrumentTrack( TrackContainer* tc, FileItem* item );
bool m_mousePressed;
QPoint m_pressPos;
//! This should only be accessed or modified when m_pphMutex is held
PlayHandle* m_previewPlayHandle;
QRecursiveMutex m_pphMutex;
QList<QAction*> getContextActions(FileItem* item, bool songEditor);
private slots:
void activateListItem(QTreeWidgetItem* item, int column);
void openInNewInstrumentTrack(FileItem* item, bool songEditor);
bool openInNewSampleTrack(FileItem* item);
void openInSlicerT(FileItem* item);
void sendToActiveInstrumentTrack(FileItem* item);
void updateDirectory(QTreeWidgetItem* item);
} ;
class FileBrowserWidgetItem : public QTreeWidgetItem
{
public:
FileBrowserWidgetItem(const QStringList& strings, int type, QTreeWidget* parent = nullptr);
virtual QString fullName(QString path = QString{}) const = 0;
};
class Directory : public FileBrowserWidgetItem
{
public:
Directory(const QString& filename, const QString& path, const QString& filter);
void update();
QString fullName(QString path = QString{}) const override
{
if( path.isEmpty() )
{
path = m_directories[0];
}
if( ! path.isEmpty() )
{
path += QDir::separator();
}
return QDir::cleanPath(path + text(0));
}
inline void addDirectory( const QString & dir )
{
m_directories.push_back( dir );
}
private:
bool addItems( const QString & path );
QPixmap m_folderPixmap = embed::getIconPixmap("folder");
QPixmap m_folderOpenedPixmap = embed::getIconPixmap("folder_opened");
QPixmap m_folderLockedPixmap = embed::getIconPixmap("folder_locked");
//! Directories that lead here
//! Initially, this is just set to the current path of a directory
//! If, however, you have e.g. 'TripleOscillator/xyz' in two of the
//! file browser's search directories 'a' and 'b', this will have two
//! entries 'a/TripleOscillator' and 'b/TripleOscillator'
//! and 'xyz' in the tree widget
QStringList m_directories;
//! Filter as used in QDir::match()
QString m_filter;
int m_dirCount;
} ;
class FileItem : public FileBrowserWidgetItem
{
public:
enum class FileType
{
Project,
Preset,
Sample,
SoundFont,
Patch,
Midi,
VstPlugin,
Unknown
} ;
enum class FileHandling
{
NotSupported,
LoadAsProject,
LoadAsPreset,
LoadByPlugin,
ImportAsProject
} ;
FileItem( QTreeWidget * parent, const QString & name,
const QString & path );
FileItem( const QString & name, const QString & path );
QString fullName(QString path = QString{}) const override
{
return QFileInfo(m_path, text(0)).absoluteFilePath();
}
inline FileType type() const
{
return( m_type );
}
inline FileHandling handling() const
{
return( m_handling );
}
inline bool isTrack() const
{
return m_handling == FileHandling::LoadAsPreset || m_handling == FileHandling::LoadByPlugin;
}
QString extension();
static QString extension( const QString & file );
static QString defaultFilters();
private:
void initPixmaps();
void determineFileType();
QString m_path;
FileType m_type;
FileHandling m_handling;
} ;
} // namespace gui
} // namespace lmms
#endif // LMMS_GUI_FILE_BROWSER_H