aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Moore <ken@ixsystems.com>2017-11-15 14:38:01 -0500
committerKen Moore <ken@ixsystems.com>2017-11-15 14:38:01 -0500
commit8d54d01f09760c78d649baed0b88aa0f80069de7 (patch)
tree7c754cf8208ed2534974dbe53f5c0a76c7cf1081
parentA bit more background threading magic. (diff)
downloadlumina-8d54d01f09760c78d649baed0b88aa0f80069de7.tar.gz
lumina-8d54d01f09760c78d649baed0b88aa0f80069de7.tar.bz2
lumina-8d54d01f09760c78d649baed0b88aa0f80069de7.zip
Add a bunch of ZFS information routines to LFileInfo.
Also utilize this ZFS info in lumina-fileinfo (if appropriate)
-rw-r--r--src-qt5/core/libLumina/LFileInfo.cpp73
-rw-r--r--src-qt5/core/libLumina/LFileInfo.h13
-rw-r--r--src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp50
-rw-r--r--src-qt5/desktop-utils/lumina-fileinfo/MainUI.h3
-rw-r--r--src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui75
-rw-r--r--src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp2
6 files changed, 213 insertions, 3 deletions
diff --git a/src-qt5/core/libLumina/LFileInfo.cpp b/src-qt5/core/libLumina/LFileInfo.cpp
index e54ce5cc..e7d2b71a 100644
--- a/src-qt5/core/libLumina/LFileInfo.cpp
+++ b/src-qt5/core/libLumina/LFileInfo.cpp
@@ -60,6 +60,31 @@ void LFileInfo::loadExtraInfo(){
}
}
+bool LFileInfo::zfsAvailable(){
+ static unsigned int avail = 2;
+ if(avail == 2){ avail = (LUtils::isValidBinary("zfs") ? 0 : 1); }
+ return (avail == 0);
+}
+
+void LFileInfo::getZfsDataset(){
+ if(zfs_ds.isEmpty()){
+ //First run - need to probe the current directory
+ bool ok = false;
+ //Use the "atime" property for this check - been around since the earliest versions of ZFS and should take no time to probe
+ QString out = LUtils::runCommand(ok, "zfs", QStringList() << "get" << "-H" << "atime" << this->canonicalFilePath() );
+ if(!ok){ zfs_ds = "."; } //just something that is not empty - but is clearly not a valid dataset
+ else{ zfs_ds = out.section("\n",0,0).section("\t",0,0).simplified(); }
+ //qDebug() << "Found Dataset:" << zfs_ds << out << ok;
+ }
+}
+
+bool LFileInfo::goodZfsDataset(){
+ if(!zfsAvailable()){ return false; }
+ getZfsDataset(); //ensure this field is populated
+ if(zfs_ds=="." || zfs_ds.isEmpty()){ return false; }
+ return true;
+}
+
//Functions for accessing the extra information
// -- Return the mimetype for the file
QString LFileInfo::mimetype(){
@@ -109,3 +134,51 @@ bool LFileInfo::isImage(){
bool LFileInfo::isAVFile(){
return (mime.startsWith("audio/") || mime.startsWith("video/") );
}
+
+bool LFileInfo::isZfsDataset(){
+ if(!goodZfsDataset()){ return false; }
+ return ( ("/"+zfs_ds.section("/",1,-1)) == this->canonicalFilePath());
+}
+
+QString LFileInfo::zfsPool(){
+ if(!goodZfsDataset()){ return ""; }
+ return zfs_ds.section("/",0,0);
+}
+
+QStringList LFileInfo::zfsSnapshots(){
+ if(!goodZfsDataset()){ return QStringList(); }
+ QString relpath = this->canonicalFilePath().remove(0, QString("/"+zfs_ds.section("/",1,-1)).length() );
+ //qDebug() << "Got Relative path:" << zfs_ds << this->canonicalFilePath() << relpath;
+ QDir dir("/"+zfs_ds.section("/",1,-1)+"/.zfs/snapshot/");
+ QStringList snaps = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Time);
+ for(int i=0; i<snaps.length(); i++){
+ if( QFile::exists(dir.absoluteFilePath(snaps[i])+relpath) ){ snaps[i].append("::::" + dir.absoluteFilePath(snaps[i])+relpath ); }
+ else{ snaps.removeAt(i); i--; }
+ }
+ return snaps;
+}
+
+QJsonObject LFileInfo::zfsProperties(){
+ QJsonObject props;
+ if(!goodZfsDataset()){ return props; }
+ bool ok = false;
+ QStringList out = LUtils::runCommand(ok, "zfs", QStringList() << "get" << "-H" << "all" << zfs_ds).split("\n");
+ //Note: Formating of zfs output: tab-delimited, with columns [dataset, property, value, source]
+ for(int i=0; i<out.length() && ok; i++){
+ if(out[i].simplified().isEmpty()){ continue; }
+ QJsonObject prop;
+ prop.insert("property", out[i].section("\t",1,1).simplified());
+ prop.insert("value", out[i].section("\t",2,2).simplified());
+ prop.insert("source", out[i].section("\t",3,-1).simplified());
+ props.insert(prop.value("property").toString(), prop);
+ }
+ return props;
+}
+
+bool LFileInfo::zfsSetProperty(QString property, QString value){
+ if(!goodZfsDataset()){ return false; }
+ bool ok = false;
+ QString info = LUtils::runCommand(ok, "zfs", QStringList() << "set" << property+"="+value << zfs_ds);
+ if(!ok){ qDebug() << "Error Setting ZFS Property:" << property+"="+value << info; }
+ return ok;
+}
diff --git a/src-qt5/core/libLumina/LFileInfo.h b/src-qt5/core/libLumina/LFileInfo.h
index 4fbf6353..df1abb65 100644
--- a/src-qt5/core/libLumina/LFileInfo.h
+++ b/src-qt5/core/libLumina/LFileInfo.h
@@ -13,13 +13,17 @@
#include <LuminaXDG.h>
#include <QString>
#include <QFileInfo>
+#include <QJsonObject>
class LFileInfo : public QFileInfo{
private:
- QString mime, icon;
+ QString mime, icon, zfs_ds;
XDGDesktop *desk;
void loadExtraInfo();
+ bool zfsAvailable();
+ void getZfsDataset(); //note: only run this if "zfsAvailable" is true
+ bool goodZfsDataset(); //simplification of the two functions above
public:
//Couple overloaded contructors
@@ -45,6 +49,13 @@ public:
bool isImage(); //Is a readable image file (for thumbnail support)
bool isVideo(); //Is a readable video file (for thumbnail support)
bool isAVFile(); //Is an audio/video file
+
+ bool isZfsDataset();
+ QString zfsPool();
+ QStringList zfsSnapshots(); //Format: "snapshot name::::path/to/snapshot"
+ QJsonObject zfsProperties();
+ bool zfsSetProperty(QString property, QString value);
+
};
typedef QList<LFileInfo> LFileInfoList;
diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp
index e64346ae..c99a781e 100644
--- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp
+++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp
@@ -191,6 +191,52 @@ void MainUI::SyncFileInfo(){
ui->tabWidget->addTab( ui->tab_deskedit, tr("XDG Shortcut") );
}
ui->tabWidget->setCurrentIndex(ui->tabWidget->indexOf(ui->tab_file) );
+ SyncZfsInfo();
+}
+
+void MainUI::SyncZfsInfo(){
+ bool showtab = false;
+ if(INFO->zfsPool().isEmpty()){
+ //Not on a ZFS pool - hide the tab if it is available
+ showtab = false;
+ }else{
+ qDebug() << "Is a ZFS Dataset:" << INFO->isZfsDataset();
+ ui->label_zfs_pool->setText(INFO->zfsPool());
+ if(INFO->isZfsDataset()){
+ ui->tree_zfs_props->clear();
+ QJsonObject props = INFO->zfsProperties();
+ QStringList keys = props.keys();
+ for(int i=0; i<keys.length(); i++){
+ ui->tree_zfs_props->addTopLevelItem( new QTreeWidgetItem(QStringList() << keys[i] << props.value(keys[i]).toObject().value("value").toString() << props.value(keys[i]).toObject().value("source").toString() ) );
+ ui->tree_zfs_props->resizeColumnToContents(0);
+ ui->tree_zfs_props->resizeColumnToContents(1);
+ }
+ ui->tree_zfs_props->setVisible(!keys.isEmpty());
+ showtab = !keys.isEmpty();
+ }else{
+ ui->tree_zfs_props->setVisible(false);
+ }
+ QStringList snaps = INFO->zfsSnapshots();
+ ui->tree_zfs_snaps->clear();
+ for(int i=0; i<snaps.length(); i++){
+ QFileInfo finfo(snaps[i].section("::::",1,-1));
+ ui->tree_zfs_snaps->addTopLevelItem( new QTreeWidgetItem(QStringList() << snaps[i].section("::::",0,0) << finfo.created().toString(Qt::SystemLocaleShortDate) << finfo.lastModified().toString(Qt::SystemLocaleShortDate) ) );
+ ui->tree_zfs_snaps->resizeColumnToContents(0);
+ }
+ ui->tree_zfs_snaps->setVisible(!snaps.isEmpty());
+ showtab = showtab || !snaps.isEmpty();
+ }
+ if(showtab){
+ //Make sure the tab is visible
+ if(ui->tabWidget->indexOf(ui->tab_zfs)<0){
+ ui->tabWidget->addTab( ui->tab_zfs, tr("Advanced") );
+ }
+ }else{
+ //hide the tab if it is visible right now
+ if(ui->tabWidget->indexOf(ui->tab_zfs)>=0){
+ ui->tabWidget->removeTab( ui->tabWidget->indexOf(ui->tab_zfs) );
+ }
+ }
}
void MainUI::SetupNewFile(){
@@ -209,6 +255,10 @@ void MainUI::SetupNewFile(){
//qDebug() << "Adding the deskedit tab";
ui->tabWidget->addTab(ui->tab_deskedit, tr("XDG Shortcut"));
}
+ //Not on a ZFS pool - hide the tab if it is available
+ if(ui->tabWidget->indexOf(ui->tab_zfs)>=0){
+ ui->tabWidget->removeTab( ui->tabWidget->indexOf(ui->tab_zfs) );
+ }
ui->tabWidget->setCurrentIndex(ui->tabWidget->indexOf(ui->tab_deskedit) );
}
diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h
index 3990f643..4e756a97 100644
--- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h
+++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h
@@ -55,7 +55,7 @@ private:
void GetDirSize(const QString dirname) const; //function to get folder size
void SyncFileInfo();
-
+ void SyncZfsInfo();
void syncXdgStruct(XDGDesktop*);
bool saveFile(QString path);
@@ -66,6 +66,7 @@ signals:
private slots:
void SetupNewFile();
+
//Initialization functions
void SetupConnections();
diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui
index 217c1a10..5139bbf7 100644
--- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui
+++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui
@@ -216,6 +216,81 @@
</item>
</layout>
</widget>
+ <widget class="QWidget" name="tab_zfs">
+ <attribute name="title">
+ <string>Advanced</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <layout class="QFormLayout" name="formLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>ZFS Pool:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_zfs_pool">
+ <property name="text">
+ <string notr="true">[pool]</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTreeWidget" name="tree_zfs_props">
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <column>
+ <property name="text">
+ <string>Property</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Value</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Source</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTreeWidget" name="tree_zfs_snaps">
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <column>
+ <property name="text">
+ <string>Snapshot</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Date Created</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Date Modified</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </widget>
<widget class="QWidget" name="tab_deskedit">
<attribute name="title">
<string>XDG Shortcut</string>
diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp
index c4b1c8d8..5a08b797 100644
--- a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp
+++ b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp
@@ -51,7 +51,7 @@ void BrowserWidget::changeDirectory(QString dir){
//videoMap.clear();
}
if(BROWSER->currentDirectory()==dir){ return; } //already on this directory
- qDebug() << "Change Directory:" << dir << historyList;
+ //qDebug() << "Change Directory:" << dir << historyList;
if( !dir.contains("/.zfs/snapshot/") ){
if(historyList.isEmpty() || !dir.isEmpty()){ historyList << dir; }
bgstack15