FileSystemModel.hpp
1 #pragma once
2 #include <Library/LibraryInterface.hpp>
3 
4 #include <score/application/GUIApplicationContext.hpp>
5 #include <score/tools/std/StringHash.hpp>
6 #include <score/widgets/IconProvider.hpp>
7 
8 #include <QFileIconProvider>
9 #include <QFileSystemModel>
10 #include <QGuiApplication>
11 #include <QMimeData>
12 #include <QSet>
13 
14 #include <ossia/detail/hash_map.hpp>
15 #include <ossia/detail/hash_map.hpp>
16 
17 namespace Library
18 {
19 
20 class FileSystemModel : public QFileSystemModel
21 {
22 public:
23  FileSystemModel(const score::GUIApplicationContext& ctx, QObject* parent)
24  : QFileSystemModel{parent}
25  {
26  setIconProvider(&score::IconProvider::instance());
27 
28  auto& lib_setup = ctx.interfaces<Library::LibraryInterfaceList>();
29  // TODO refactor
30  QSet<QString> types{// score-specific
31  "*.score",
32  "*.cue",
33  "*.device",
34  "*.oscquery",
35  "*.json"
36 
37  // JS scripts
38  ,
39  "*.js",
40  "*.qml",
41  "*.script"
42 
43  // Faust, other audio stuff
44  ,
45  "*.dsp",
46  "*.mid"};
47 
48  for(const LibraryInterface& lib : lib_setup)
49  {
50  auto lst = lib.acceptedFiles();
51  for(const auto& ext : lib.acceptedFiles())
52  {
53  types.insert("*." + ext);
54  }
55  }
56 
57  // QFileSystemModel is case-sensitive, so we at least handle the ALL-CAPS EXTENSIONS
58  // **floppy drive noises buzzing in the background**
59  {
60  auto copy = types;
61  for(auto t : copy)
62  {
63  types.insert(t.toUpper());
64  }
65  }
66 
67  setNameFilters(types.values());
68  setResolveSymlinks(true);
69  setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
70 
71  for(auto& lib : lib_setup)
72  {
73  for(const auto& str : lib.acceptedMimeTypes())
74  {
75  m_mimeTypes.push_back(str);
76  m_mimeActions[str] = &lib;
77  }
78  }
79  }
80 
81 #if defined(__clang__)
82  static constexpr bool supportsDisablingSorting() noexcept
83  {
84  return []<typename T>(T* fsm) constexpr {
85  return requires { fsm->setOption(T::DontSort); };
86  }((QFileSystemModel*)nullptr);
87  }
88 
89  void setSorting(bool b) noexcept
90  {
91  [b]<typename T>(T& self) {
92  if constexpr(T::supportsDisablingSorting())
93  {
94  static_assert(T::supportsDisablingSorting());
95  self.setOption(T::DontSort, !b);
96  }
97  }(*this);
98  }
99 
100  bool isSorting() noexcept
101  {
102  return []<typename T>(T& fsm) {
103  if constexpr(supportsDisablingSorting())
104  {
105  static_assert(requires { fsm.setOption(T::DontSort); });
106  return !fsm.testOption(T::DontSort);
107  }
108  else
109  {
110  return true;
111  }
112  }(*this);
113  }
114 #else
115  static constexpr bool supportsDisablingSorting() noexcept { return false; }
116  void setSorting(bool b) noexcept { }
117  bool isSorting() noexcept { return true; }
118 #endif
119 
120  Qt::ItemFlags flags(const QModelIndex& index) const override
121  {
122  Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled
123  | Qt::ItemIsDropEnabled;
124 
125  if(!isDir(index))
126  f |= Qt::ItemIsEditable;
127 
128  return f;
129  }
130 
131  QStringList mimeTypes() const override { return m_mimeTypes; }
132 
133  bool dropMimeData(
134  const QMimeData* data, Qt::DropAction action, int row, int column,
135  const QModelIndex& parent) override
136  {
137  const QFileInfo f = fileInfo(parent);
138  const QDir d = f.isDir() ? QDir(f.canonicalFilePath()) : f.absoluteDir();
139  for(const auto& fmt : data->formats())
140  {
141  auto it = m_mimeActions.find(fmt);
142  if(it != m_mimeActions.end())
143  {
144  if(it->second->onDrop(*data, row, column, d))
145  return true;
146  }
147  }
148 
149  return false;
150  }
151 
152  QVariant data(const QModelIndex& index, int role) const override
153  {
154  if(role == Qt::DecorationRole)
155  {
156  if(isDir(index))
157  return score::IconProvider::folderIcon();
158  else
159  return {};
160  }
161  return QFileSystemModel::data(index, role);
162  }
163 
164  QStringList m_mimeTypes;
165  ossia::hash_map<QString, LibraryInterface*> m_mimeActions;
166 };
167 }
Definition: FileSystemModel.hpp:21
Definition: LibraryInterface.hpp:22
Definition: LibraryInterface.hpp:44
void insert(std::unique_ptr< score::InterfaceBase > e) final override
insert Register a new factory.
Definition: InterfaceList.hpp:98
const T & interfaces() const
Access to a specific interface list.
Definition: ApplicationContext.hpp:67
Specializes ApplicationContext with the QMainWindow.
Definition: GUIApplicationContext.hpp:15