aboutsummaryrefslogtreecommitdiff
path: root/lumina-fm/DirData.h
blob: ee2c84290f9eef52b4c2e3e313b92976d9005487 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//===========================================
//  Lumina-DE source code
//  Copyright (c) 2015, Ken Moore
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================
//  This is the backend classes for fetching directory information/contents
//===========================================
#ifndef _LUMINA_FM_BACKGROUND_DATA_CLASSES_H
#define _LUMINA_FM_BACKGROUND_DATA_CLASSES_H

#include <QObject>
#include <QList>
#include <QString>
#include <QFileInfo>
#include  <QDir>

#include <LuminaXDG.h>
#include <LuminaUtils.h>

//Need some extra information not usually available by a QFileInfo
class LFileInfo : public QFileInfo{
private:
	QString mime, icon;
	XDGDesktop desk;

	void loadExtraInfo(){
	  //Now load the extra information
	  if(this->isDir()){
	    mime = "inode/directory";
	    //Special directory icons
	    QString name = this->fileName().toLower();
	    if(name=="desktop"){ icon = "user-desktop"; }
	    else if(name=="tmp"){ icon = "folder-temp"; }
	    else if(name=="video" || name=="videos"){ icon = "folder-video"; }
	    else if(name=="music" || name=="audio"){ icon = "folder-sound"; }
	    else if(name=="projects" || name=="devel"){ icon = "folder-development"; }
	    else if(name=="notes"){ icon = "folder-txt"; }
	    else if(name=="downloads"){ icon = "folder-downloads"; }
	    else if(name=="documents"){ icon = "folder-documents"; }
	    else if(name=="images" || name=="pictures"){ icon = "folder-image"; }
	    else if( !this->isReadable() ){ icon = "folder-locked"; }
	  }else if( this->suffix()=="desktop"){
	    mime = "application/x-desktop";
	    icon = "application-x-desktop"; //default value
	    bool ok = false;
	    desk = LXDG::loadDesktopFile(this->absoluteFilePath(), ok);
	    if(ok){
	      //use the specific desktop file info (if possible)
	      if(!desk.icon.isEmpty()){ icon = desk.icon; }
	    }
	  }else{
	    //Generic file, just determine the mimetype
	    mime = LXDG::findAppMimeForFile(this->fileName());
	  }
	}
	
public:
	LFileInfo(QString filepath){ //overloaded contructor
	  this->setFile(filepath);
	  loadExtraInfo();
	}	
	LFileInfo(QFileInfo info){ //overloaded contructor
	  this->swap(info); //use the given QFileInfo without re-loading it
	  loadExtraInfo();
	}		
	~LFileInfo(){}
	
	//Functions for accessing the extra information
	// -- Return the mimetype for the file
	QString mimetype(){
	  return mime;
	}
	
	// -- Return the icon to use for this file
	QString iconfile(){
	  return (icon.isEmpty() ? mime: icon); //Fall back on the mimetype if no icon listed
	}
	
	// -- Check if this is an XDG desktop file
	bool isDesktopFile(){
	  return (!desk.filePath.isEmpty());	
	}
	
	// -- Allow access to the XDG desktop data structure
	const XDGDesktop* XDG(){
	  return &desk;
	}
	
	// -- Check if this is a readable image file (for thumbnail support)
	bool isImage(){
	  if(!mime.startsWith("image/")){ return false; } //quick return for non-image files
	  //Check the Qt subsystems to see if this image file can be read
	  return ( !LUtils::imageExtensions().filter(this->suffix().toLower()).isEmpty() );
	}
	
	bool isAVFile(){
	  return (mime.startsWith("audio/") || mime.startsWith("video/") );
	}
};

class LDirInfoList{
public:
	//Internal variables
	QDateTime lastcheck;
	QList<LFileInfo> list;
	QStringList fileNames; //list of filenames for comparison/checking sorting
	QString dirpath; //directory this structure was reading
	bool hashidden;

	//Access Functions
	LDirInfoList(QString path = ""){
	  dirpath = path;
	  list.clear();
	  fileNames.clear();
	  hashidden = false;
	}
	~LDirInfoList(){}

	//(re)Load a directory contents
	void update(bool showhidden = false){
	  if(dirpath.isEmpty()){ return; } //nothing to do
	  //Assemble the structures
	  QDir dir(dirpath);
	  hashidden = showhidden;
	  if(!dir.exists()){
	    list.clear();
	    fileNames.clear();
	    dirpath.clear(); //invalid directory now
	    return;
	  }
	  QFileInfoList dirlist;
	  //Fill the structure
	  list.clear();
	  fileNames.clear();
	  lastcheck = QDateTime::currentDateTime();
	  if(showhidden){ dirlist = dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden , QDir::Name | QDir::DirsFirst); }
	  else{ dirlist = dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot , QDir::Name | QDir::DirsFirst); }
	  //Simple add routine - can make it more dynamic/selective about updating individual items later
	    for(int i=0; i<dirlist.length(); i++){
	      list << LFileInfo(dirlist[i]); //generate the extra information for this file
	      fileNames << dirlist[i].fileName(); //add the filename to the list
	    }	
	  
	}

};

//This class is designed to be run in a background thread and get all the necessary info for a directory listing
class DirData : public QObject{
	Q_OBJECT
private:
	QHash<QString, LDirInfoList> HASH; //Where we cache any info for rapid access later

signals:
	void DirDataAvailable(QString, QList<LFileInfo>); //[ID, DATA]

public:
	//Variables
	bool showHidden;

	//Functions
	DirData(){ 
	  showHidden = false; 
	}
	~DirData(){}

public slots:
	void GetDirData(QString ID, QString dirpath){ 
	  //The ID is used when returning the info in a moment
	  if(!HASH.contains(dirpath)){
	    //New directory (not previously loaded)
	    LDirInfoList info(dirpath);
	      info.update(showHidden);
	    HASH.insert(dirpath, info);
	  }else{
	    //See if the saved info needs to be updated
	    if( (HASH.value(dirpath).hashidden != showHidden) || (QFileInfo(dirpath).lastModified() > HASH.value(dirpath).lastcheck) ){
	      HASH[dirpath].update(showHidden);
	    }
	    
	  }
	  emit DirDataAvailable(ID, HASH.value(dirpath).list);
	}
	
};

#endif
bgstack15