aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/desktop-utils/lumina-fm/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/desktop-utils/lumina-fm/widgets')
-rw-r--r--src-qt5/desktop-utils/lumina-fm/widgets/DDListWidgets.h125
-rw-r--r--src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.cpp1049
-rw-r--r--src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.h229
-rw-r--r--src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.ui527
-rw-r--r--src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp734
-rw-r--r--src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.h173
-rw-r--r--src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui249
7 files changed, 1263 insertions, 1823 deletions
diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DDListWidgets.h b/src-qt5/desktop-utils/lumina-fm/widgets/DDListWidgets.h
index e3de9b0e..254362fd 100644
--- a/src-qt5/desktop-utils/lumina-fm/widgets/DDListWidgets.h
+++ b/src-qt5/desktop-utils/lumina-fm/widgets/DDListWidgets.h
@@ -24,6 +24,8 @@
#include <QUrl>
#include <QDir>
+#include <LUtils.h>
+
//==============
// LIST WIDGET
//==============
@@ -42,22 +44,30 @@ public:
this->setFlow(QListView::TopToBottom);
this->setWrapping(true);
this->setMouseTracking(true);
- //this->setSortingEnabled(true); //This sorts *only* by name - type is not preserved
+ this->setSortingEnabled(true); //This sorts *only* by name - type is not preserved
+ //this->setStyleSheet("QListWidget::item{ border: 1px solid transparent; border-radius: 5px; background-color: transparent;} QListWidget::item:hover{ border-color: black; } QListWidget::item:focus{ border-color: lightblue; }");
}
~DDListWidget(){}
signals:
void DataDropped(QString, QStringList); //Dir path, List of commands
-
+ void GotFocus();
+
protected:
+ void focusInEvent(QFocusEvent *ev){
+ QListWidget::focusInEvent(ev);
+ emit GotFocus();
+ }
+
void startDrag(Qt::DropActions act){
QList<QListWidgetItem*> items = this->selectedItems();
if(items.length()<1){ return; }
QList<QUrl> urilist;
for(int i=0; i<items.length(); i++){
- urilist << QUrl::fromLocalFile(items[i]->whatsThis().section("::::",1,100));
+ urilist << QUrl::fromLocalFile(items[i]->whatsThis());
}
//Create the mime data
+ //qDebug() << "Start Drag:" << urilist;
QMimeData *mime = new QMimeData;
mime->setUrls(urilist);
//Create the drag structure
@@ -76,19 +86,23 @@ protected:
ev->acceptProposedAction(); //allow this to be dropped here
}else{
ev->ignore();
- }
+ }
}
void dragMoveEvent(QDragMoveEvent *ev){
if(ev->mimeData()->hasUrls() && !this->whatsThis().isEmpty() ){
//Change the drop type depending on the data/dir
QString home = QDir::homePath();
- if( this->whatsThis().startsWith(home) ){ ev->setDropAction(Qt::MoveAction); }
- else{ ev->setDropAction(Qt::CopyAction); }
+ //qDebug() << "Drag Move:" << home << this->whatsThis();
+ if( this->whatsThis().startsWith(home) ){ ev->setDropAction(Qt::MoveAction); this->setCursor(Qt::DragMoveCursor); }
+ else{ ev->setDropAction(Qt::CopyAction); this->setCursor(Qt::DragCopyCursor);}
ev->acceptProposedAction(); //allow this to be dropped here
+ //this->setCursor(Qt::CrossCursor);
}else{
+ this->setCursor(Qt::ForbiddenCursor);
ev->ignore();
}
+ this->update();
}
void dropEvent(QDropEvent *ev){
@@ -99,7 +113,8 @@ protected:
//See if the item under the drop point is a directory or not
QListWidgetItem *it = this->itemAt( ev->pos());
if(it!=0){
- QFileInfo info(it->whatsThis().section("::::",1,100));
+ //qDebug() << "Drop Item:" << it->whatsThis();
+ QFileInfo info(it->whatsThis());
if(info.isDir() && info.isWritable()){
dirpath = info.absoluteFilePath();
}
@@ -110,11 +125,13 @@ protected:
foreach(const QUrl &url, ev->mimeData()->urls()){
const QString filepath = url.toLocalFile();
//If the target file is modifiable, assume a move - otherwise copy
- if(QFileInfo(filepath).isWritable() && (filepath.startsWith(home) && dirpath.startsWith(home))){ files << "cut::::"+filepath; }
- else{ files << "copy::::"+filepath; }
+ if(QFileInfo(filepath).isWritable() && (filepath.startsWith(home) && dirpath.startsWith(home))){
+ if(filepath.section("/",0,-2)!=dirpath){ files << "cut::::"+filepath; } //don't "cut" a file into the same dir
+ }else{ files << "copy::::"+filepath; }
}
- //qDebug() << "Drop Event:" << dirpath;
- emit DataDropped( dirpath, files );
+ //qDebug() << "Drop Event:" << dirpath << files;
+ if(!files.isEmpty()){ emit DataDropped( dirpath, files ); }
+ this->setCursor(Qt::ArrowCursor);
}
void mouseReleaseEvent(QMouseEvent *ev){
@@ -155,14 +172,19 @@ public:
signals:
void DataDropped(QString, QStringList); //Dir path, List of commands
-
+ void GotFocus();
+
protected:
+ void focusInEvent(QFocusEvent *ev){
+ QTreeWidget::focusInEvent(ev);
+ emit GotFocus();
+ }
void startDrag(Qt::DropActions act){
QList<QTreeWidgetItem*> items = this->selectedItems();
if(items.length()<1){ return; }
QList<QUrl> urilist;
for(int i=0; i<items.length(); i++){
- urilist << QUrl::fromLocalFile(items[i]->whatsThis(0).section("::::",1,100));
+ urilist << QUrl::fromLocalFile(items[i]->whatsThis(0));
}
//Create the mime data
QMimeData *mime = new QMimeData;
@@ -205,7 +227,7 @@ protected:
//See if the item under the drop point is a directory or not
QTreeWidgetItem *it = this->itemAt( ev->pos());
if(it!=0){
- QFileInfo info(it->whatsThis(0).section("::::",1,100));
+ QFileInfo info(it->whatsThis(0));
if(info.isDir() && info.isWritable()){
dirpath = info.absoluteFilePath();
}
@@ -216,9 +238,10 @@ protected:
QString home = QDir::homePath();
foreach(const QUrl &url, ev->mimeData()->urls()){
const QString filepath = url.toLocalFile();
- //If the target file is modifiable, assume a move - otherwise copy
- if(QFileInfo(filepath).isWritable() && (filepath.startsWith(home) && dirpath.startsWith(home)) ){ files << "cut::::"+filepath; }
- else{ files << "copy::::"+filepath; }
+ //If the target file is modifiable, assume a move - otherwise copy
+ if(QFileInfo(filepath).isWritable() && (filepath.startsWith(home) && dirpath.startsWith(home))){
+ if(filepath.section("/",0,-2)!=dirpath){ files << "cut::::"+filepath; } //don't "cut" a file into the same dir
+ }else{ files << "copy::::"+filepath; }
}
//qDebug() << "Drop Event:" << dirpath;
emit DataDropped( dirpath, files );
@@ -237,4 +260,70 @@ protected:
else{ QTreeWidget::mouseMoveEvent(ev); } //pass it along to the widget
}*/
};
-#endif \ No newline at end of file
+
+/*
+ * Virtual class for managing the sort of folders/files items. The problem with base class is that it only manages texts fields and
+ * we have dates and sizes.
+ *
+ * On this class, we overwrite the function operator<.
+ */
+
+class CQTreeWidgetItem : public QTreeWidgetItem {
+public:
+ CQTreeWidgetItem(int type = Type) : QTreeWidgetItem(type) {}
+ CQTreeWidgetItem(const QStringList & strings, int type = Type) : QTreeWidgetItem(strings, type) {}
+ CQTreeWidgetItem(QTreeWidget * parent, int type = Type) : QTreeWidgetItem(parent, type) {}
+ CQTreeWidgetItem(QTreeWidget * parent, const QStringList & strings, int type = Type) : QTreeWidgetItem(parent, strings, type) {}
+ CQTreeWidgetItem(QTreeWidget * parent, QTreeWidgetItem * preceding, int type = Type) : QTreeWidgetItem(parent, preceding, type) {}
+ CQTreeWidgetItem(QTreeWidgetItem * parent, int type = Type) : QTreeWidgetItem(parent, type) {}
+ CQTreeWidgetItem(QTreeWidgetItem * parent, const QStringList & strings, int type = Type) : QTreeWidgetItem(parent, strings, type) {}
+ CQTreeWidgetItem(QTreeWidgetItem * parent, QTreeWidgetItem * preceding, int type = Type) : QTreeWidgetItem(parent, preceding, type) {}
+ virtual ~CQTreeWidgetItem() {}
+ inline virtual bool operator<(const QTreeWidgetItem &tmp) const {
+ int column = this->treeWidget()->sortColumn();
+ // We are in date text
+ if(column == 3 || column == 4){
+ return this->whatsThis(column) < tmp.whatsThis(column);
+ // We are in size text
+ }else if(column == 1) {
+ QString text = this->text(column);
+ QString text_tmp = tmp.text(column);
+ double filesize, filesize_tmp;
+ // On folders, text is empty so we check for that
+ // In case we are in folders, we put -1 for differentiate of regular files with 0 bytes.
+ // Doing so, all folders we'll be together instead of mixing with files with 0 bytes.
+ if(text.isEmpty())
+ filesize = -1;
+ else
+ filesize = LUtils::DisplaySizeToBytes(text);
+ if(text_tmp.isEmpty())
+ filesize_tmp = -1;
+ else
+ filesize_tmp = LUtils::DisplaySizeToBytes(text_tmp);
+ return filesize < filesize_tmp;
+
+ //Name column - still sort by type too (folders first)
+ }else if(column == 0 && (this->text(2).isEmpty() || tmp.text(2).isEmpty()) ){
+ if(this->text(2) != tmp.text(2)){ return this->text(2).isEmpty(); }
+ }
+ // In other cases, we trust base class implementation
+ return QTreeWidgetItem::operator<(tmp);
+ }
+};
+
+//Item override for sorting purposes of list widget items
+class CQListWidgetItem : public QListWidgetItem {
+public:
+ CQListWidgetItem(const QIcon &icon, const QString &text, QListWidget *parent = Q_NULLPTR) : QListWidgetItem(icon,text,parent) {}
+ virtual ~CQListWidgetItem() {}
+ inline virtual bool operator<(const QListWidgetItem &tmp) const {
+ QString type = this->data(Qt::UserRole).toString();
+ QString tmptype = tmp.data(Qt::UserRole).toString();
+ //Sort by type first
+ if(type!=tmptype){ return (QString::compare(type,tmptype)<0); }
+ //Then sort by name using the normal rules
+ return QListWidgetItem::operator<(tmp);
+ }
+};
+
+#endif
diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.cpp
deleted file mode 100644
index a23c9aec..00000000
--- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.cpp
+++ /dev/null
@@ -1,1049 +0,0 @@
-//===========================================
-// Lumina-DE source code
-// Copyright (c) 2015, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-#include "DirWidget.h"
-#include "ui_DirWidget.h"
-
-#include <QMessageBox>
-#include <QCursor>
-#include <QClipboard>
-#include <QMimeData>
-#include <QTimer>
-#include <QInputDialog>
-#include <QScrollBar>
-#include <QSettings>
-#include <QtConcurrent/QtConcurrentRun>
-
-#include <LuminaOS.h>
-#include <LuminaXDG.h>
-#include <LuminaUtils.h>
-
-#include "../ScrollDialog.h"
-
-#define DEBUG 0
-
-
-const QString sessionsettings_config_file = QDir::homePath() + "/.lumina/LuminaDE/sessionsettings.conf";
-
-DirWidget::DirWidget(QString objID, QWidget *parent) : QWidget(parent), ui(new Ui::DirWidget){
- ui->setupUi(this); //load the designer file
- ID = objID;
- //Assemble the toolbar for the widget
- toolbar = new QToolBar(this);
- toolbar->setContextMenuPolicy(Qt::CustomContextMenu);
- toolbar->setFloatable(false);
- toolbar->setMovable(false);
- toolbar->setOrientation(Qt::Horizontal);
- toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly);
- //toolbar->setIconSize(QSize(32,32));
- ui->toolbar_layout->addWidget(toolbar);
- // - Add the buttons to the toolbar
- toolbar->addAction(ui->actionBack);
- toolbar->addAction(ui->actionUp);
- toolbar->addAction(ui->actionHome);
- line_dir = new QLineEdit(this);
- toolbar->addWidget(line_dir);
- toolbar->addAction(ui->actionStopLoad);
- toolbar->addAction(ui->actionClose_Browser);
- //Add the browser widgets
- listWidget = new DDListWidget(this);
- treeWidget = new DDTreeWidget(this);
- ui->browser_layout->addWidget(listWidget);
- ui->browser_layout->addWidget(treeWidget);
- //Create the keyboard shortcuts
- /*copyFilesShort = new QShortcut( QKeySequence(tr("Ctrl+C")), this);
- pasteFilesShort = new QShortcut( QKeySequence(tr("Ctrl+V")), this);
- cutFilesShort = new QShortcut( QKeySequence(tr("Ctrl+X")), this);
- deleteFilesShort = new QShortcut( QKeySequence(tr("Delete")), this);*/
- //Create the filesystem watcher
- watcher = new QFileSystemWatcher(this);
- synctimer = new QTimer(this);
- synctimer->setInterval(300); // 300 millisecond pause (combine simultaneous signals from the watcher)
- synctimer->setSingleShot(true);
- //Now update the rest of the UI
- canmodify = false; //initial value
- contextMenu = new QMenu(this);
- setDateFormat();
- setShowDetails(true);
- setShowThumbnails(true);
- UpdateIcons();
- UpdateText();
- setupConnections();
-}
-
-DirWidget::~DirWidget(){
- stopload = true; //just in case another thread is still loading/running
-}
-
-void DirWidget::setFocusLineDir() {
- line_dir->setFocus();
- line_dir->selectAll();
-}
-
-void DirWidget::cleanup(){
- stopload = true; //just in case another thread is still loading/running
- if(thumbThread.isRunning()){ thumbThread.waitForFinished(); } //this will stop really quickly with the flag set
-}
-
-void DirWidget::ChangeDir(QString dirpath){
- stopload = true; //just in case it is still loading
- emit LoadDirectory(ID, dirpath);
-}
-
-void DirWidget::setDirCompleter(QCompleter *comp){
- line_dir->setCompleter(comp);
-}
-
-QString DirWidget::id(){
- return ID;
-}
-
-QString DirWidget::currentDir(){
- return CDIR;
-}
-
-void DirWidget::setShowDetails(bool show){
- if(show!=showDetails){
- //View about to change - ensure the selection gets transferred too
- tmpSel = currentSelection();
- }
- showDetails = show;
- listWidget->setVisible(!showDetails);
- treeWidget->setVisible(showDetails);
- this->refresh();
-}
-
-void DirWidget::setShowSidebar(bool show){
- ui->group_actions->setVisible(show);
-}
-
-void DirWidget::setShowThumbnails(bool show){
- showThumbs = show;
- this->refresh();
-}
-
-void DirWidget::setDetails(QList<DETAILTYPES> list){
- listDetails = list;
- //Need to re-create the header item as well
- CQTreeWidgetItem *it = new CQTreeWidgetItem();
- int nmcol = -1; int typecol = -1;
- for(int t=0; t<listDetails.length(); t++){
- switch(listDetails[t]){
- case NAME:
- it->setText(t,tr("Name"));
- nmcol = t;
- break;
- case SIZE:
- it->setText(t,tr("Size"));
- break;
- case TYPE:
- it->setText(t, tr("Type"));
- typecol = t;
- break;
- case DATEMOD:
- it->setText(t, tr("Date Modified") );
- break;
- case DATECREATE:
- it->setText(t, tr("Date Created") );
- break;
- }
- }
- treeWidget->setHeaderItem(it);
- //Now reset the sorting (alphabetically, dirs first)
- if(nmcol>=0){ treeWidget->sortItems(nmcol, Qt::AscendingOrder); } // sort by name
- if(typecol>=0){ treeWidget->sortItems(typecol, Qt::AscendingOrder); } //sort by type first
-
- if(CDIR.isEmpty() || !showDetails){ return; } //don't need to reload dir if details are not visible
- this->refresh();
-}
-
-void DirWidget::setThumbnailSize(int px){
- bool larger = listWidget->iconSize().height() < px;
- listWidget->setIconSize(QSize(px,px));
- treeWidget->setIconSize(QSize(px,px));
- if(CDIR.isEmpty() || !larger ){ return; } //don't need to reload icons unless the new size is larger
- this->refresh();
-}
-
-void DirWidget::setShowCloseButton(bool show){
- ui->actionClose_Browser->setVisible(show);
-}
-
-QStringList DirWidget::getDateFormat() {
- return date_format;
-}
-
-// This function is only called if user changes sessionsettings. By doing so, operations like sorting by date
-// are faster because the date format is already stored in DirWidget::date_format static variable
-void DirWidget::setDateFormat() {
- if(!date_format.isEmpty())
- date_format.clear();
- QSettings settings("LuminaDE","sessionsettings");
- // If value doesn't exist or is not setted, empty string is returned
- date_format << settings.value("DateFormat").toString();
- date_format << settings.value("TimeFormat").toString();
-}
-
-
-// ================
-// PUBLIC SLOTS
-// ================
-void DirWidget::LoadDir(QString dir, QList<LFileInfo> list){
- if(dir.isEmpty()){ return; } //nothing to do
- QTime time;
- if(DEBUG){time.start(); }
- qDebug() << "Load Dir:" << dir;
- QString lastdir = CDIR; //for some checks later
- QString lastbasedir = normalbasedir;
- CDIR = dir;
- if(CDIR.endsWith("/") && CDIR.length() > 1){ CDIR.chop(1); }
- CLIST = list; //save for later
- canmodify = QFileInfo(CDIR).isWritable();
- if(DEBUG){ qDebug() << "Clear UI:" <<time.elapsed(); }
- //Clear the status text
- if(!canmodify){ui->label_status->setText(tr("(Limited Access) ")); }
- else{ ui->label_status->setText(""); }
- //Hide the extra buttons for a moment
- ui->tool_goToPlayer->setVisible(false);
- ui->tool_goToImages->setVisible(false);
- ui->tool_new_dir->setVisible(canmodify);
- ui->tool_new_file->setVisible(canmodify);
- //Set the drag/drop info as appripriate
- if(canmodify){
- listWidget->setWhatsThis(CDIR);
- treeWidget->setWhatsThis(CDIR);
- }else{
- listWidget->setWhatsThis("");
- treeWidget->setWhatsThis("");
- }
- bool updateThumbs = (lastdir != CDIR);
- //Determine if this is an internal ZFS snapshot
- bool loadsnaps = false;
- if(DEBUG){ qDebug() << "Load Snap Info:" << time.elapsed(); }
- if( dir.contains(ZSNAPDIR) ){
- //This is a zfs snapshot - only update the saved paths necessary to rotate between snapshots/system
- snaprelpath = dir.section(ZSNAPDIR,1,1000).section("/",1,1000); //the relative path inside the snapshot
- if(snaprelpath.endsWith("/")){ snaprelpath.chop(1); }
- normalbasedir = dir.section(ZSNAPDIR,0,0)+"/"+snaprelpath; //Update the new base directory
- if(normalbasedir.endsWith("/")){ normalbasedir.chop(1); }
- line_dir->setText(normalbasedir);
- //See if this was a manual move to the directory, or an internal move
- QString tmp = dir.section(ZSNAPDIR,0,0);
- if(tmp != snapbasedir.section(ZSNAPDIR,0,0)){
- loadsnaps = true; //different snapshot loaded - need to update internally
- }
- }else{
- //This is a normal directory - prompt for snapshot information
- line_dir->setText(CDIR);
- normalbasedir = CDIR;
- if(!snapbasedir.isEmpty()){ watcher->removePath(snapbasedir); }
- snapbasedir.clear();
- loadsnaps = true;
- }
- if(loadsnaps){
- //kick this off while still loading the dir contents
- ui->group_snaps->setEnabled(false); //to prevent the snap updates to be automatically used
- ui->group_snaps->setVisible(false);
- ui->slider_snap->setRange(1,1);
- emit findSnaps(ID, normalbasedir);
- }
-
- if(DEBUG){ qDebug() << "Update History:" <<time.elapsed(); }
- //Now update the history for this browser
- //qDebug() << "History:" << history << normalbasedir << lastbasedir;
- if(!history.isEmpty() && history.last() == normalbasedir && lastbasedir!=normalbasedir ){
- //We went back one - remove this from the history
- history.takeLast();
- ui->actionBack->setEnabled(!history.isEmpty());
- //qDebug() << " - Duplicate: removed item";
- }else if(lastbasedir!=normalbasedir){ //not a refresh or internal snapshot change
- //qDebug() << " - New History Item:" << normalbasedir;
- history << normalbasedir;
- ui->actionBack->setEnabled(history.length()>1);
- }
- if(DEBUG){ qDebug() << "Update Watcher:" << time.elapsed(); }
- //Clear the current watcher
- if(!watcher->directories().isEmpty()){ watcher->removePaths(watcher->directories()); }
- if(!watcher->files().isEmpty()){ watcher->removePaths(watcher->files()); }
- watcher->addPath(CDIR);
- // add sessionsettings to watcher so date_format can be update based on user settings
- watcher->addPath(sessionsettings_config_file);
- ui->actionStopLoad->setVisible(true);
- stopload = false;
- //Clear the display widget (if a new directory)
- if(DEBUG){ qDebug() << "Clear Browser Widget:" << time.elapsed(); }
- double scrollpercent = -1;
- if(updateThumbs){ needThumbs.clear(); }
- if(lastbasedir != normalbasedir){
- if(showDetails){ treeWidget->clear(); }
- else{ listWidget->clear(); }
- QApplication::processEvents(); //make sure it is cleared right away
- }else{
- //Need to be smarter about which items need to be removed
- // - compare the old/new lists and remove any items not in the new listing (new items taken care of below)
- QStringList newfiles; //just the filenames
- for(int i=0; i<CLIST.length(); i++){ newfiles << CLIST[i].fileName(); }
- if(showDetails){
- for(int i=0; i<treeWidget->topLevelItemCount(); i++){
- if( !newfiles.contains(treeWidget->topLevelItem(i)->whatsThis(0).section("/",-1)) ){
- if(!updateThumbs){ needThumbs.removeAll( treeWidget->topLevelItem(i)->whatsThis(0).section("::::",1,50)); }
- delete treeWidget->takeTopLevelItem(i);
- i--;
- }
- }
- QApplication::processEvents(); //make sure the scrollbar is up to date after removals
- scrollpercent = treeWidget->verticalScrollBar()->value()/( (double) treeWidget->verticalScrollBar()->maximum());
- }else{
- for(int i=0; i<listWidget->count(); i++){
- if( !newfiles.contains(listWidget->item(i)->text()) ){
- if(!updateThumbs){ needThumbs.removeAll( listWidget->item(i)->whatsThis().section("::::",1,50)); }
- delete listWidget->takeItem(i);
- i--;
- }
- }
- QApplication::processEvents(); //make sure the scrollbar is up to date after removals
- scrollpercent = listWidget->horizontalScrollBar()->value()/( (double) listWidget->horizontalScrollBar()->maximum());
- }
- } //end check for CDIR reload
- //Now fill the display widget
- bool hasimages, hasmultimedia;
- hasimages = hasmultimedia = false;
- int numdirs = 0;
- qint64 filebytes = 0;
- //Setup the timer to see when we should process events
- /*QTimer updatetime;
- updatetime.setInterval(1000); //1 second updates
- updatetime.setSingleShot(true);
- updatetime.start();*/
- QTime updatetime = QTime::currentTime().addMSecs(500);
- if(DEBUG){ qDebug() << "Start Loop over items:" << time.elapsed(); }
- for(int i=0; i<list.length(); i++){
- if(stopload){ ui->actionStopLoad->setVisible(false); return; } //stop right now
- if(!hasimages && list[i].isImage()){ hasimages = true; ui->tool_goToImages->setVisible(true); }
- else if(!hasmultimedia && list[i].isAVFile()){ hasmultimedia = true; ui->tool_goToPlayer->setVisible(true); }
- //Update statistics
- if(list[i].isDir()){ numdirs++; }
- else{ filebytes += list[i].size(); }
- watcher->addPath(list[i].absoluteFilePath());
- if(showDetails){
- //Now create all the individual items for the details tree
- CQTreeWidgetItem *it;
- bool addnew = false;
- //See if an item already exists for this file
- QList<QTreeWidgetItem*> items = treeWidget->findItems(list[i].fileName(),Qt::MatchExactly,0); //NOTE: This requires column 0 to be the name
- if(items.isEmpty()){
- it = new CQTreeWidgetItem();
- addnew = true;
- }else{
- // Safe downcasting because CQTreeWidgetItem only redefines the virtual function bool opearot<. Not new methos added.
- it = static_cast<CQTreeWidgetItem *> (items.first());
- }
- //Now update the entry contents
- it->setWhatsThis(0, QString(canmodify ? "cut": "copy")+"::::"+list[i].absoluteFilePath());
- for(int t=0; t<listDetails.length(); t++){
- switch(listDetails[t]){
- case NAME:
- it->setText(t,list[i].fileName());
- it->setStatusTip(t, list[i].fileName());
- //Since the icon/image is based on the filename - only update this for a new item
- // (This is the slowest part of the routine)
- if(list[i].isImage()&& (addnew || updateThumbs)){
- if(showThumbs){
- it->setIcon(t, LXDG::findIcon("fileview-preview","image-x-generic") );
- needThumbs << list[i].absoluteFilePath();
- }else{ it->setIcon(t, LXDG::findIcon(list[i].iconfile(),"image-x-generic") ); }
- }else if(addnew){
- it->setIcon(t, LXDG::findIcon(list[i].iconfile(),"unknown") );
- }
- break;
- case SIZE:
- if(!list[i].isDir()){
- it->setText(t, LUtils::BytesToDisplaySize(list[i].size()) );
- }
- break;
- case TYPE:
- it->setText(t, list[i].mimetype());
- break;
- case DATEMOD:
- {
- QStringList datetime_format = getDateFormat();
- // Save datetime in WhatThis value. Lately will be used by CQTreeWidgetItem for sorting by date
- it->setWhatsThis(t, list[i].lastModified().toString("yyyyMMddhhmmsszzz"));
- // Default configurition. Fallback to Qt::DefaultLocaleShortDate for formats
- if(datetime_format.at(0).isEmpty() && datetime_format.at(1).isEmpty())
- it->setText(t, list[i].lastModified().toString(Qt::DefaultLocaleShortDate) );
- // Date is setted but time not. Time goes to default
- else if(!datetime_format.at(0).isEmpty() && datetime_format.at(1).isEmpty())
- it->setText(t, list[i].lastModified().date().toString(datetime_format.at(0)) + " " + list[i].lastModified().time().toString(Qt::DefaultLocaleShortDate));
- // Time is setted but date not. Date goes to default
- else if(datetime_format.at(0).isEmpty() && !datetime_format.at(1).isEmpty())
- it->setText(t, list[i].lastModified().date().toString(Qt::DefaultLocaleShortDate) + " " + list[i].lastModified().time().toString(datetime_format.at(1)));
- // Both time and date setted.
- else
- it->setText(t, list[i].lastModified().date().toString(datetime_format.at(0)) + " " + list[i].lastModified().time().toString(datetime_format.at(1)));
- break;
- }
- case DATECREATE:
- {
- QStringList datetime_format = getDateFormat();
- it->setWhatsThis(DATECREATE, list[i].lastModified().toString("yyyyMMddhhmmsszzz"));
- if(datetime_format.at(0).isEmpty() && datetime_format.at(1).isEmpty())
- it->setText(t, list[i].lastModified().toString(Qt::DefaultLocaleShortDate) );
- else if(!datetime_format.at(0).isEmpty() && datetime_format.at(1).isEmpty())
- it->setText(t, list[i].lastModified().date().toString(datetime_format.at(0)) + " " + list[i].lastModified().time().toString(Qt::DefaultLocaleShortDate));
- else if(datetime_format.at(0).isEmpty() && !datetime_format.at(1).isEmpty())
- it->setText(t, list[i].lastModified().date().toString(Qt::DefaultLocaleShortDate) + " " + list[i].lastModified().time().toString(datetime_format.at(1)));
- else
- it->setText(t, list[i].lastModified().date().toString(datetime_format.at(0)) + " " + list[i].lastModified().time().toString(datetime_format.at(1)));
- break;
- }
- }
- }
- if(addnew){ treeWidget->addTopLevelItem(it); }
- if(tmpSel.contains(list[i].absoluteFilePath())){ it->setSelected(true); }
- if(lastdir == CDIR+"/"+list[i].fileName()){
- treeWidget->setCurrentItem(it);
- treeWidget->scrollToItem(it);
- }
- }else{
- //Create all the individual items for the basic list
- QListWidgetItem *it;
- //See if there is an existing item to re-use
- bool addnew = false;
- QList<QListWidgetItem*> items = listWidget->findItems(list[i].fileName(), Qt::MatchExactly);
- if(items.isEmpty()){
- it = new QListWidgetItem();
- addnew = true;
- }else{ it = items.first(); }
-
- it->setWhatsThis( QString(canmodify ? "cut": "copy")+"::::"+list[i].absoluteFilePath()); //used for drag and drop
- it->setText(list[i].fileName());
- it->setStatusTip(list[i].fileName());
- //Since the icon/image is based on the filename - only update this for a new items (non-thumbnail)
- // (This is the slowest part of the routine)
- if(list[i].isImage() && (addnew || updateThumbs) ){
- if(showThumbs){
- it->setIcon(LXDG::findIcon("fileview-preview","image-x-generic") );
- needThumbs << list[i].absoluteFilePath();
- }else{ it->setIcon(LXDG::findIcon(list[i].iconfile(),"image-x-generic") ); }
- }else if(addnew){
- it->setIcon(LXDG::findIcon(list[i].iconfile(),"unknown") );
- }
- listWidget->addItem(it);
- if(tmpSel.contains(list[i].absoluteFilePath())){ it->setSelected(true); }
- if(lastdir == CDIR+"/"+list[i].fileName()){
- listWidget->setCurrentItem(it);
- listWidget->scrollToItem(it);
- }
- }
- if(QTime::currentTime() > updatetime){ QApplication::processEvents(); updatetime = QTime::currentTime().addMSecs(500); }//keep the UI snappy while loading a directory
- if(DEBUG){ qDebug() << " - item finished:" << i << time.elapsed(); }
- }
- tmpSel.clear();
- if(DEBUG){ qDebug() << "Done with item loop:" << time.elapsed() << list.length(); }
- ui->actionStopLoad->setVisible(false);
- //Another check to ensure the current item is visible (or return to the same scroll position)
- if(stopload){ return; } //stop right now
- if(scrollpercent<0){
- if(showDetails){
- for(int t=0; t<treeWidget->columnCount(); t++){treeWidget->resizeColumnToContents(t); }
- if(treeWidget->currentItem()!=0){ treeWidget->scrollToItem(treeWidget->currentItem()); }
- }else{
- if(listWidget->currentItem()!=0){ listWidget->scrollToItem(listWidget->currentItem()); }
- }
- }else{
- if(showDetails){
- treeWidget->verticalScrollBar()->setValue( qRound(treeWidget->verticalScrollBar()->maximum()*scrollpercent) );
- }else{
- listWidget->horizontalScrollBar()->setValue( qRound(listWidget->horizontalScrollBar()->maximum()*scrollpercent) );
- }
- }
-
-
- if(stopload){ return; } //stop right now
- if(DEBUG){ qDebug() << "Assemble Status Message:" << time.elapsed(); }
- //Assemble any status message
- QString stats = QString(tr("Capacity: %1")).arg(LOS::FileSystemCapacity(CDIR));
- if(list.length()>0){
- stats.prepend("\t");
- if(numdirs < list.length()){
- //Has Files
- stats.prepend( QString(tr("Files: %1 (%2)")).arg(QString::number(list.length()-numdirs), LUtils::BytesToDisplaySize(filebytes)) );
- }
- if(numdirs > 0){
- //Has Dirs
- if(numdirs<list.length()){ stats.prepend(" / "); }//has files output already
- stats.prepend( QString(tr("Dirs: %1")).arg(QString::number(numdirs)) );
- }
-
- }
- if(stopload){ return; } //stop right now
- if(!canmodify){ stats.prepend(tr("(Limited Access) ")); }
- ui->label_status->setText( stats.simplified() );
- if(DEBUG){ qDebug() << "DONE:" << time.elapsed(); }
- if(showThumbs){ thumbThread = QtConcurrent::run(this, &DirWidget::startLoadThumbs); }
-}
-
-void DirWidget::LoadSnaps(QString basedir, QStringList snaps){
- //Save these value internally for use later
- qDebug() << "ZFS Snapshots available:" << basedir << snaps;
- snapbasedir = basedir;
- snapshots = snaps;
- if(!snapbasedir.isEmpty()){ watcher->addPath(snapbasedir); } //add this to the watcher in case snapshots get created/removed
- //Now update the UI as necessary
- if(ui->tool_snap->menu()==0){
- ui->tool_snap->setMenu(new QMenu(this));
- connect(ui->tool_snap->menu(), SIGNAL(triggered(QAction*)), this, SLOT(direct_snap_selected(QAction*)) );
- }
- ui->tool_snap->menu()->clear();
- for(int i=0; i<snapshots.length(); i++){
- QAction *tmp = ui->tool_snap->menu()->addAction(snapshots[i]);
- tmp->setWhatsThis(snapshots[i]);
- }
- ui->slider_snap->setRange(0, snaps.length());
- if(CDIR.contains(ZSNAPDIR)){
- //The user was already within a snapshot - figure out which one and set the slider appropriately
- int index = snaps.indexOf( CDIR.section(ZSNAPDIR,1,1).section("/",0,0) );
- if(index < 0){ index = snaps.length(); } //unknown - load the system (should never happen)
- ui->slider_snap->setValue(index);
- }else{
- ui->slider_snap->setValue(snaps.length()); //last item (normal system)
- }
- on_slider_snap_valueChanged();
- QApplication::processEvents(); //let the slider changed signal get thrown away before we re-enable the widget
- ui->group_snaps->setEnabled(!snaps.isEmpty());
- ui->group_snaps->setVisible(!snaps.isEmpty());
- ui->tool_snap_newer->setEnabled(ui->slider_snap->value() < ui->slider_snap->maximum());
- ui->tool_snap_older->setEnabled(ui->slider_snap->value() > ui->slider_snap->minimum());
-}
-
-void DirWidget::refresh(){
- if(!CDIR.isEmpty() && ~ID.isEmpty()){
- stopload = true; //just in case it is still loading
- emit LoadDirectory(ID, CDIR);
- }
-}
-
-void DirWidget::refreshButtons(){
- SelectionChanged();
-}
-
-//Theme change functions
-void DirWidget::UpdateIcons(){
- //ui->tool_addNewFile->setIcon( LXDG::findIcon("document-new",""));
- //ui->tool_addToDir->setIcon( LXDG::findIcon("folder-new","") );
-
- //Snapshot buttons
- ui->tool_snap_newer->setIcon(LXDG::findIcon("go-next-view","") );
- ui->tool_snap_older->setIcon(LXDG::findIcon("go-previous-view","") );
- //Bottom-Action Buttons
- ui->tool_goToImages->setIcon( LXDG::findIcon("fileview-preview","") );
- ui->tool_goToPlayer->setIcon( LXDG::findIcon("applications-multimedia","") );
- ui->tool_new_file->setIcon( LXDG::findIcon("document-new","") );
- ui->tool_new_dir->setIcon( LXDG::findIcon("folder-new","") );
- //Side-Action Buttons
- ui->tool_act_run->setIcon( LXDG::findIcon("run-build-file","") );
- ui->tool_act_runwith->setIcon( LXDG::findIcon("run-build-configure","") );
- ui->tool_act_cut->setIcon( LXDG::findIcon("edit-cut","") );
- ui->tool_act_copy->setIcon( LXDG::findIcon("edit-copy","") );
- ui->tool_act_paste->setIcon( LXDG::findIcon("edit-paste","") );
- ui->tool_act_rename->setIcon( LXDG::findIcon("edit-rename","") );
- ui->tool_act_rm->setIcon( LXDG::findIcon("edit-delete","") );
- ui->tool_act_fav->setIcon( LXDG::findIcon("bookmark-toolbar","") );
- //ToolBar Buttons
- ui->actionBack->setIcon( LXDG::findIcon("go-previous","") );
- ui->actionUp->setIcon( LXDG::findIcon("go-up","") );
- ui->actionHome->setIcon( LXDG::findIcon("go-home","") );
- ui->actionStopLoad->setIcon( LXDG::findIcon("dialog-cancel","") );
- ui->actionClose_Browser->setIcon( LXDG::findIcon("dialog-close","") );
-}
-
-void DirWidget::UpdateText(){
- ui->retranslateUi(this);
-}
-
-void DirWidget::UpdateButtons(){
- SelectionChanged();
-}
-
-//Keyboard Shortcuts triggered
-void DirWidget::TryRenameSelection(){
- on_tool_act_rename_clicked();
-}
-
-void DirWidget::TryCutSelection(){
- on_tool_act_cut_clicked();
-}
-
-void DirWidget::TryCopySelection(){
- on_tool_act_copy_clicked();
-}
-
-void DirWidget::TryPasteSelection(){
- on_tool_act_paste_clicked();
-}
-
-void DirWidget::TryDeleteSelection(){
- on_tool_act_rm_clicked();
-}
-
-// =================
-// PRIVATE
-// =================
-void DirWidget::setupConnections(){
- //Info routines
- connect(treeWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OpenContextMenu()) );
- connect(listWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OpenContextMenu()) );
- connect(treeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(SelectionChanged()) );
- connect(listWidget, SIGNAL(itemSelectionChanged()), this, SLOT(SelectionChanged()) );
-
- //Activation routines
- connect(treeWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(on_tool_act_run_clicked()) );
- connect(treeWidget, SIGNAL(DataDropped(QString, QStringList)), this, SIGNAL(PasteFiles(QString, QStringList)) );
- connect(listWidget, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(on_tool_act_run_clicked()) );
- connect(listWidget, SIGNAL(DataDropped(QString, QStringList)), this, SIGNAL(PasteFiles(QString, QStringList)) );
- connect(line_dir, SIGNAL(returnPressed()), this, SLOT(dir_changed()) );
-
- //Keyboard Shortcuts
- /*connect(copyFilesShort, SIGNAL(activated()), this, SLOT( on_tool_act_copy_clicked() ) );
- connect(cutFilesShort, SIGNAL(activated()), this, SLOT( on_tool_act_cut_clicked() ) );
- connect(pasteFilesShort, SIGNAL(activated()), this, SLOT( on_tool_act_paste_clicked() ) );
- connect(deleteFilesShort, SIGNAL(activated()), this, SLOT( on_tool_act_rm_clicked() ) );*/
-
- //Filesystem Watcher
- connect(watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(startSync(const QString &)) );
- connect(watcher, SIGNAL(fileChanged(const QString&)), this, SLOT(startSync(const QString &)) ); //just in case
- connect(synctimer, SIGNAL(timeout()), this, SLOT(refresh()) );
-
- //Thumbnail loader
- connect(this, SIGNAL(ThumbLoaded(QString, QIcon)), this, SLOT(showThumb(QString, QIcon)) );
-}
-
-QStringList DirWidget::currentSelection(){
- QStringList out;
- if(showDetails){
- QList<QTreeWidgetItem*> sel = treeWidget->selectedItems();
- for(int i=0; i<sel.length(); i++){
- out << sel[i]->whatsThis(0).section("::::",1,100); //absolute file path
- }
- }else{
- QList<QListWidgetItem*> sel = listWidget->selectedItems();
- for(int i=0; i<sel.length(); i++){
- out << sel[i]->whatsThis().section("::::",1,100); //absolute file path
- }
- }
- out.removeDuplicates();
- return out;
-}
-
-// =================
-// PRIVATE SLOTS
-// =================
-void DirWidget::startLoadThumbs(){
- //This just runs through the dir and loads all the thumbnails as needed
- if(DEBUG){ qDebug() << "Start Loading Thumbnails:" << needThumbs; }
- if(needThumbs.isEmpty()){ return; }
- needThumbs.removeDuplicates(); //just in case
- //QTime updatetime = QTime::currentTime().addMSecs(500);
- while(!needThumbs.isEmpty() && !stopload){
- QString file = needThumbs.takeFirst();
- QIcon ico(QPixmap(file).scaled(listWidget->iconSize(),Qt::IgnoreAspectRatio, Qt::FastTransformation) );
- emit ThumbLoaded(file, ico);
- }
-}
-
-void DirWidget::showThumb(QString file, QIcon ico){
- if(showDetails){
- //Use the tree widget
- QList<QTreeWidgetItem*> items = treeWidget->findItems(file.section("/",-1), Qt::MatchExactly);
- if(items.isEmpty() || stopload){ return; } //invalid item for some reason
- QTreeWidgetItem *it = items.first();
- it->setIcon(0, ico );
- }else{
- //Use the list widget
- QList<QListWidgetItem*> items = listWidget->findItems(file.section("/",-1), Qt::MatchExactly);
- if(items.isEmpty() || stopload){ return; } //invalid item for some reason
- if(stopload){ return; } //stop right now
- QListWidgetItem *it = items.first();
- it->setIcon(ico);
- }
-}
-
-//UI BUTTONS
-// -- Left Action Buttons
-void DirWidget::on_tool_act_cut_clicked(){
- QStringList sel = currentSelection();
- qDebug() << "Cutting Items to clipboard:" << sel;
- if(sel.isEmpty()){ return; }
- emit CutFiles(sel);
-}
-
-void DirWidget::on_tool_act_copy_clicked(){
- QStringList sel = currentSelection();
- if(sel.isEmpty()){ return; }
- qDebug() << "Copying Items to clipboard:" << sel;
- emit CopyFiles(sel);
-}
-
-void DirWidget::on_tool_act_fav_clicked(){
- QStringList sel = currentSelection();
- if(sel.isEmpty()){ return; }
-
- emit FavoriteFiles(sel);
-}
-
-void DirWidget::on_tool_act_paste_clicked(){
- qDebug() << "Pasting Items from clipboard:" << CDIR;
- emit PasteFiles(CDIR, QStringList()); //use the clipboard for pasting
-}
-
-void DirWidget::on_tool_act_rename_clicked(){
- QStringList sel = currentSelection();
- if(sel.isEmpty()){ return; }
- emit RenameFiles(sel);
-}
-
-void DirWidget::on_tool_act_rm_clicked(){
- QStringList sel = currentSelection();
- if(sel.isEmpty()){ return; }
- qDebug() << "Deleting selected Items:" << sel;
- emit RemoveFiles(sel);
-}
-
-void DirWidget::on_tool_act_run_clicked(){
- QStringList sel = currentSelection();
- if(sel.isEmpty()){ return; }
- QStringList dirs;
- for(int i=0; i<sel.length(); i++){
- if(QFileInfo(sel[i]).isDir()){
- dirs << sel[i];
- }else{
- QProcess::startDetached("lumina-open \""+sel[i]+"\"");
- }
- }
- if(!dirs.isEmpty()){
- stopload = true; //just in case it is still loading
- emit LoadDirectory(ID, dirs.takeFirst()); //load the first directory in this widget
- }
- if(!dirs.isEmpty()){
- emit OpenDirectories(dirs);
- }
-}
-
-void DirWidget::on_tool_act_runwith_clicked(){
- QStringList sel = currentSelection();
- if(sel.isEmpty()){ return; }
- for(int i=0; i<sel.length(); i++){
- QProcess::startDetached("lumina-open -select \""+sel[i]+"\""); //use absolute paths
- }
-}
-
-// -- Bottom Action Buttons
-void DirWidget::on_tool_goToImages_clicked(){
- QStringList sel = currentSelection();
- if(sel.isEmpty()){ emit ViewFiles(CLIST); }
- else{
- //Just use the files from the current selection
- LFileInfoList list;
- for(int i=0; i<CLIST.length(); i++){
- if(CLIST[i].isImage() && sel.contains(CLIST[i].absoluteFilePath()) ){
- list << CLIST[i]; //add to the list
- }
- }
- if(!list.isEmpty()){ emit ViewFiles(list); }
- else{ emit ViewFiles(CLIST); } //invalid file(s) selected - just do everything
- }
-}
-
-void DirWidget::on_tool_goToPlayer_clicked(){
- QStringList sel = currentSelection();
- if(sel.isEmpty()){ emit PlayFiles(CLIST); }
- else{
- //Just use the files from the current selection
- LFileInfoList list;
- for(int i=0; i<CLIST.length(); i++){
- if(CLIST[i].isAVFile() && sel.contains(CLIST[i].absoluteFilePath()) ){
- list << CLIST[i]; //add to the list
- }
- }
- if(!list.isEmpty()){ emit PlayFiles(list); }
- else{ emit PlayFiles(CLIST); } //invalid file(s) selected - just do everything
- }
-}
-
-void DirWidget::on_tool_new_file_clicked(){
- if(!canmodify){ return; } //cannot create anything here
- //Prompt for the new filename
- bool ok = false;
- QString newdocument = QInputDialog::getText(this, tr("New Document"), tr("Name:"), QLineEdit::Normal, "", \
- &ok, 0, Qt::ImhFormattedNumbersOnly | Qt::ImhUppercaseOnly | Qt::ImhLowercaseOnly);
- if(!ok || newdocument.isEmpty()){ return; }
- //Create the empty file
- QString full = CDIR;
- if(!full.endsWith("/")){ full.append("/"); }
- QFile file(full+newdocument);
- if(file.open(QIODevice::ReadWrite)){
- //If successfully opened, it has created a blank file
- file.close();
- }else{
- QMessageBox::warning(this, tr("Error Creating Document"), tr("The document could not be created. Please ensure that you have the proper permissions."));
- }
- //just in case the watcher does not work for this filesystem -queue up a sync
- if(!synctimer->isActive()){ synctimer->start(); }
-}
-
-void DirWidget::on_tool_new_dir_clicked(){
- if(!canmodify){ return; } //cannot create anything here
- //Prompt for the new dir name
- bool ok = false;
- QString newdir = QInputDialog::getText(this, tr("New Directory"), tr("Name:"), QLineEdit::Normal, "", \
- &ok, 0, Qt::ImhFormattedNumbersOnly | Qt::ImhUppercaseOnly | Qt::ImhLowercaseOnly);
- if(!ok || newdir.isEmpty()){ return; }
- //Now create the new dir
- QString full = CDIR;
- if(!full.endsWith("/")){ full.append("/"); }
- QDir dir(full); //open the current dir
- full.append(newdir); //append the new name to the current dir
- //Verify that the new dir does not already exist
- if(dir.exists(full)){
- QMessageBox::warning(this, tr("Invalid Name"), tr("A file or directory with that name already exists! Please pick a different name."));
- QTimer::singleShot(0,this, SLOT(on_tool_addToDir_clicked()) ); //repeat this function
- }else{
- if(!dir.mkdir(newdir) ){
- QMessageBox::warning(this, tr("Error Creating Directory"), tr("The directory could not be created. Please ensure that you have the proper permissions to modify the current directory."));
- }
- }
- //just in case the watcher does not work for this filesystem -queue up a sync
- if(!synctimer->isActive()){ synctimer->start(); }
-}
-
-// -- Top Snapshot Buttons
-void DirWidget::on_tool_snap_newer_clicked(){
- ui->slider_snap->setValue( ui->slider_snap->value()+1 );
-}
-
-void DirWidget::on_tool_snap_older_clicked(){
- ui->slider_snap->setValue( ui->slider_snap->value()-1 );
-}
-
-void DirWidget::on_slider_snap_valueChanged(int val){
- bool labelsonly = false;
- if(val==-1){ val = ui->slider_snap->value(); labelsonly=true; }
- //Update the snapshot interface
- ui->tool_snap_newer->setEnabled(val < ui->slider_snap->maximum());
- ui->tool_snap_older->setEnabled(val > ui->slider_snap->minimum());
- if(val >= snapshots.length() || val < 0){
- ui->tool_snap->setText(tr("Current"));
- }else if(QFile::exists(snapbasedir+snapshots[val])){
- ui->tool_snap->setText( QFileInfo(snapbasedir+snapshots[val]).lastModified().toString(Qt::DefaultLocaleShortDate) );
- }
- //Exit if a non-interactive snapshot change
- if(!ui->group_snaps->isEnabled() || labelsonly){ return; } //internal change - do not try to change the actual info
- //Determine which snapshot is now selected
- QString dir;
- if(DEBUG){ qDebug() << "Changing snapshot:" << CDIR << val << snapbasedir; }
- stopload = true; //stop any currently-loading procedures
- if(val >= snapshots.length() || val < 0){ //active system selected
- if(DEBUG){ qDebug() << " - Load Active system:" << normalbasedir; }
- dir = normalbasedir;
- }else{
- dir = snapbasedir+snapshots[val]+"/";
- if(!QFile::exists(dir)){
- //This snapshot must have been removed in the background by pruning tools
- // move to a newer snapshot or the current base dir as necessary
- qDebug() << "Snapshot no longer available:" << dir;
- qDebug() << " - Reloading available snapshots";
- emit findSnaps(ID, normalbasedir);
- return;
- }
- //if(snaprelpath.isEmpty()){
- //Need to figure out the relative path within the snapshot
- snaprelpath = normalbasedir.section(snapbasedir.section(ZSNAPDIR,0,0), 1,1000);
- if(DEBUG){ qDebug() << " - new snapshot-relative path:" << snaprelpath; }
- //}
- dir.append(snaprelpath);
- dir.replace("//","/"); //just in case any duplicate slashes from all the split/combining
- if(DEBUG){ qDebug() << " - Load Snapshot:" << dir; }
- }
- //Make sure this directory exists, and back up as necessary
- if(dir.isEmpty()){ return; }
- //Load the newly selected snapshot
- stopload = true; //just in case it is still loading
- emit LoadDirectory(ID, dir);
-}
-
-void DirWidget::direct_snap_selected(QAction *act){
- QString snap = act->whatsThis();
- int val = snapshots.indexOf(snap);
- if(val<0){ return; }
- else{ ui->slider_snap->setValue(val); }
-}
-
-//Top Toolbar buttons
-void DirWidget::on_actionBack_triggered(){
- if(history.isEmpty()){ return; } //cannot do anything
- QString dir = history.takeLast();
- //qDebug() << "Go Back:" << dir << normalbasedir << history.last();
- if(dir == normalbasedir){
- dir = history.takeLast();
- }
- stopload = true; //just in case it is still loading
- emit LoadDirectory(ID, dir);
-}
-
-void DirWidget::on_actionUp_triggered(){
- QString dir = CDIR.section("/",0,-2);
- if(dir.isEmpty())
- dir = "/";
- //Quick check to ensure the directory exists
- while(!QFile::exists(dir) && !dir.isEmpty()){
- dir = dir.section("/",0,-2); //back up one additional dir
- }
- stopload = true; //just in case it is still loading
- emit LoadDirectory(ID, dir);
-}
-
-void DirWidget::on_actionHome_triggered(){
- stopload = true; //just in case it is still loading
- emit LoadDirectory(ID, QDir::homePath());
-}
-
-void DirWidget::on_actionStopLoad_triggered(){
- stopload = true;
- ui->actionStopLoad->setVisible(false);
-}
-
-void DirWidget::dir_changed(){
- QString dir = line_dir->text().simplified();
- //Run the dir through the user-input checks
- dir = LUtils::PathToAbsolute(dir);
- qDebug() << "Dir:" << dir;
- //Quick check to ensure the directory exists
- while(!QFile::exists(dir) && !dir.isEmpty()){
- dir = dir.section("/",0,-2); //back up one additional dir
- }
- qDebug() << " - Now Dir:" << dir;
- stopload = true; //just in case it is still loading
- emit LoadDirectory(ID, dir);
-}
-
-void DirWidget::on_actionClose_Browser_triggered(){
- emit CloseBrowser(ID);
-}
-
-// - Other Actions without a specific button on the side
-void DirWidget::fileCheckSums(){
- QStringList files = currentSelection();
- if(files.isEmpty()){ return; }
- qDebug() << "Run Checksums:" << files;
- QStringList info = LOS::Checksums(files);
- qDebug() << " - Info:" << info;
- if(info.isEmpty() || (info.length() != files.length()) ){ return; }
- for(int i=0; i<info.length(); i++){
- info[i] = QString("%2\n\t(%1)").arg(files[i].section("/",-1), info[i]);
- }
- ScrollDialog dlg(this);
- dlg.setWindowTitle( tr("File Checksums:") );
- dlg.setWindowIcon( LXDG::findIcon("document-encrypted","") );
- dlg.setText(info.join("\n"));
- dlg.exec();
- /*QMessageBox dlg(this);
- dlg.setWindowFlags( Qt::Dialog );
- dlg.setWindowTitle( tr("File Checksums") );
- dlg.setDetailedText(info.join("\n"));
- dlg.exec();*/
- //QMessageBox::information(this, tr("File Checksums"), info.join("\n") );
-}
-
-void DirWidget::fileProperties(){
- QStringList sel = currentSelection();
- if(sel.isEmpty()){ return; }
- if(!LUtils::isValidBinary("lumina-fileinfo")){
- //It should never get to this point due to checks earlier - but just in case...
- QMessageBox::warning(this, tr("Missing Utility"), tr("The \"lumina-fileinfo\" utility could not be found on the system. Please install it first.") );
- return;
- }
- for(int i=0; i<sel.length(); i++){
- QProcess::startDetached("lumina-fileinfo \""+sel[i]+"\""); //use absolute paths
- }
-}
-
-void DirWidget::openTerminal(){
- emit LaunchTerminal(CDIR);
-}
-
-//Browser Functions
-void DirWidget::OpenContextMenu(){
- //First generate the context menu based on the selection
- QStringList sel = currentSelection();
- contextMenu->clear();
- if(!sel.isEmpty()){
- contextMenu->addAction(LXDG::findIcon("run-build-file",""), tr("Open"), this, SLOT(on_tool_act_run_clicked()) );
- contextMenu->addAction(LXDG::findIcon("run-build-configure",""), tr("Open With..."), this, SLOT(on_tool_act_runwith_clicked()) );
-
- contextMenu->addAction(LXDG::findIcon("edit-rename",""), tr("Rename..."), this, SLOT(on_tool_act_rename_clicked()) )->setEnabled(canmodify);
- contextMenu->addAction(LXDG::findIcon("document-encrypted",""), tr("View Checksums..."), this, SLOT(fileCheckSums()) );
- contextMenu->addSeparator();
- }
- //Now add the general selection options
- contextMenu->addAction(LXDG::findIcon("edit-cut",""), tr("Cut Selection"), this, SLOT(on_tool_act_cut_clicked()) )->setEnabled(canmodify && !sel.isEmpty());
- contextMenu->addAction(LXDG::findIcon("edit-copy",""), tr("Copy Selection"), this, SLOT(on_tool_act_copy_clicked()) )->setEnabled(!sel.isEmpty());
- contextMenu->addAction(LXDG::findIcon("edit-paste",""), tr("Paste"), this, SLOT(on_tool_act_paste_clicked()) )->setEnabled(QApplication::clipboard()->mimeData()->hasFormat("x-special/lumina-copied-files") && canmodify);
- contextMenu->addSeparator();
- contextMenu->addAction(LXDG::findIcon("edit-delete",""), tr("Delete Selection"), this, SLOT(on_tool_act_rm_clicked()) )->setEnabled(canmodify&&!sel.isEmpty());
- if(LUtils::isValidBinary("lumina-fileinfo")){
- contextMenu->addSeparator();
- contextMenu->addAction(LXDG::findIcon("edit-find-replace",""), tr("File Properties..."), this, SLOT(fileProperties()) )->setEnabled(!sel.isEmpty());
- }
- contextMenu->addSeparator();
- contextMenu->addAction(LXDG::findIcon("system-search",""), tr("Open Terminal here"), this, SLOT(openTerminal()));
-
- //Now open the menu at the current cursor location
- contextMenu->popup(QCursor::pos());
-}
-
-void DirWidget::SelectionChanged(){
- //Go through and enable/disable the buttons as necessary
- bool hasselection = !currentSelection().isEmpty();
- ui->tool_act_copy->setEnabled(hasselection);
- ui->tool_act_cut->setEnabled(hasselection && canmodify);
- ui->tool_act_fav->setEnabled(hasselection);
- ui->tool_act_paste->setEnabled(canmodify && QApplication::clipboard()->mimeData()->hasFormat("x-special/lumina-copied-files") );
- ui->tool_act_rename->setEnabled(hasselection && canmodify);
- ui->tool_act_rm->setEnabled(hasselection && canmodify);
- ui->tool_act_run->setEnabled(hasselection);
- ui->tool_act_runwith->setEnabled(hasselection);
-}
-
-void DirWidget::startSync(const QString &file){
- //Update date_format based on user settings
- if(file == sessionsettings_config_file){ setDateFormat(); }
- else if(file == snapbasedir){ emit findSnaps(ID, normalbasedir); } //snapshot list changed
- else if(file == normalbasedir){
- if(synctimer->isActive()){ synctimer->stop(); } //already starting a sync - restart the timer
- synctimer->start();
- }else{
- //Some file in the directory got changed - start the time for a dir reload
- // -- This prevents a directory from refreshing constantly if a file within the directory is changing all the time (such as a log file)
- if(!synctimer->isActive()){ synctimer->start(); }
- }
-}
-
-//====================
-// PROTECTED
-//====================
-void DirWidget::mouseReleaseEvent(QMouseEvent *ev){
- static Qt::MouseButtons backmap = Qt::BackButton | Qt::ExtraButton5;
- //qDebug() << "Mouse Click:" << ev->button();
- if(backmap.testFlag(ev->button())){
- ev->accept();
- on_actionBack_triggered();
- //}else if(ev->button()==Qt::ForwardButton()){
- //ev->accept();
- }else{
- ev->ignore(); //not handled here
- }
-}
diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.h b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.h
deleted file mode 100644
index 3ef9940b..00000000
--- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.h
+++ /dev/null
@@ -1,229 +0,0 @@
-//===========================================
-// Lumina-DE source code
-// Copyright (c) 2015, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-#ifndef _LUMINA_FM_DIRECTORY_BROWSER_WIDGET_H
-#define _LUMINA_FM_DIRECTORY_BROWSER_WIDGET_H
-
-#include <QList>
-#include <QWidget>
-#include <QObject>
-#include <QMenu>
-#include <QToolBar>
-#include <QLineEdit>
-#include <QShortcut>
-#include <QFileSystemWatcher>
-#include <QTimer>
-#include <QFuture>
-
-#include "../DirData.h"
-#include "DDListWidgets.h"
-
-#define ZSNAPDIR QString("/.zfs/snapshot/")
-
-namespace Ui{
- class DirWidget;
-};
-
-class DirWidget : public QWidget{
- Q_OBJECT
-public:
- enum DETAILTYPES{ NAME, SIZE, TYPE, DATEMOD, DATECREATE};
- DirWidget(QString objID, QWidget *parent = 0); //needs a unique ID (to distinguish from other DirWidgets)
- ~DirWidget();
-
- void cleanup(); //called before the browser is closed down
-
- //Directory Managment
- void ChangeDir(QString dirpath);
- void setDirCompleter(QCompleter *comp);
-
- //Information
- QString id();
- QString currentDir();
-
- //View Settings
- void setShowDetails(bool show);
- void setShowSidebar(bool show);
- void setShowThumbnails(bool show);
- void setDetails(QList<DETAILTYPES> list); //Which details to show and in which order (L->R)
- void setThumbnailSize(int px);
- void setShowCloseButton(bool show);
- void setFocusLineDir();
-
- //Date format for show items
- QStringList getDateFormat();
- void setDateFormat();
-
-public slots:
- void LoadDir(QString dir, LFileInfoList list);
- void LoadSnaps(QString basedir, QStringList snaps);
-
- //Refresh options
- void refresh(); //Refresh current directory
- void refreshButtons(); //Refresh action buttons only
-
- //Theme change functions
- void UpdateIcons();
- void UpdateText();
-
- //Button updates
- void UpdateButtons();
-
- //Keyboard Shortcuts triggered
- void TryRenameSelection();
- void TryCutSelection();
- void TryCopySelection();
- void TryPasteSelection();
- void TryDeleteSelection();
-
-private:
- Ui::DirWidget *ui;
- QString ID, CDIR; //unique ID assigned by the parent and the current dir path
- LFileInfoList CLIST; //current item list (snap or not)
- QString normalbasedir, snapbasedir, snaprelpath; //for maintaining directory context while moving between snapshots
- QStringList snapshots, needThumbs, tmpSel;
- bool showDetails, showThumbs, canmodify, stopload; //which widget to use for showing items
- QList<DETAILTYPES> listDetails;
- QMenu *contextMenu;
- QFuture<void> thumbThread;
- //The Toolbar and associated items
- QToolBar *toolbar;
- QLineEdit *line_dir;
- QStringList history;
- //The drag and drop brower widgets
- DDListWidget *listWidget;
- DDTreeWidget *treeWidget;
-
- //Keyboard Shortcuts
- //QShortcut *copyFilesShort, *cutFilesShort, *pasteFilesShort, *deleteFilesShort;
- //Watcher to determine when the dir changes
- QFileSystemWatcher *watcher;
- QTimer *synctimer;
-
- //Functions for internal use
- void setupConnections();
- QStringList currentSelection();
- QStringList date_format;
-
-private slots:
- //Internal loading of thumbnails
- void startLoadThumbs();
- void showThumb(QString file, QIcon ico);
-
- //UI BUTTONS/Actions
- // -- Left Action Buttons
- void on_tool_act_copy_clicked();
- void on_tool_act_cut_clicked();
- void on_tool_act_fav_clicked();
- void on_tool_act_paste_clicked();
- void on_tool_act_rename_clicked();
- void on_tool_act_rm_clicked();
- void on_tool_act_run_clicked();
- void on_tool_act_runwith_clicked();
- // -- Bottom Action Buttons
- void on_tool_goToImages_clicked();
- void on_tool_goToPlayer_clicked();
- void on_tool_new_file_clicked();
- void on_tool_new_dir_clicked();
- // -- Top Snapshot Buttons
- void on_tool_snap_newer_clicked();
- void on_tool_snap_older_clicked();
- void on_slider_snap_valueChanged(int val = -1);
- void direct_snap_selected(QAction*);
-
- //Top Toolbar buttons
- void on_actionBack_triggered();
- void on_actionUp_triggered();
- void on_actionHome_triggered();
- void on_actionStopLoad_triggered();
- void dir_changed(); //user manually changed the directory
- void on_actionClose_Browser_triggered();
-
- // - Other Actions without a specific button on the side
- void fileCheckSums();
- void fileProperties();
- void openTerminal();
-
-
- //Browser Functions
- void OpenContextMenu();
- void SelectionChanged();
- void startSync(const QString &file); //used internally to collect/pause before updating the dir
-
-signals:
- //Directory loading/finding signals
- void OpenDirectories(QStringList); //Directories to open in other tabs/columns
- void LoadDirectory(QString, QString); //ID, dirpath (Directory to load here)
- void findSnaps(QString, QString); //ID, dirpath (Request snapshot information for a directory)
- void CloseBrowser(QString); //ID (Request that this browser be closed)
-
- //External App/Widget launching
- void PlayFiles(LFileInfoList); //open in multimedia player
- void ViewFiles(LFileInfoList); //open in slideshow
- void LaunchTerminal(QString); //dirpath
-
- //System Interactions
- void CutFiles(QStringList); //file selection
- void CopyFiles(QStringList); //file selection
- void PasteFiles(QString, QStringList); //current dir
- void FavoriteFiles(QStringList); //file selection
- void RenameFiles(QStringList); //file selection
- void RemoveFiles(QStringList); //file selection
-
- //Internal thumbnail loading system (multi-threaded)
- void ThumbLoaded(QString, QIcon);
-
-protected:
- void mouseReleaseEvent(QMouseEvent *);
-
-};
-
-/*
- * Virtual class for managing the sort of folders/files items. The problem with base class is that it only manages texts fields and
- * we have dates and sizes.
- *
- * On this class, we overwrite the function operator<.
- */
-
-class CQTreeWidgetItem : public QTreeWidgetItem {
-public:
- CQTreeWidgetItem(int type = Type) : QTreeWidgetItem(type) {}
- CQTreeWidgetItem(const QStringList & strings, int type = Type) : QTreeWidgetItem(strings, type) {}
- CQTreeWidgetItem(QTreeWidget * parent, int type = Type) : QTreeWidgetItem(parent, type) {}
- CQTreeWidgetItem(QTreeWidget * parent, const QStringList & strings, int type = Type) : QTreeWidgetItem(parent, strings, type) {}
- CQTreeWidgetItem(QTreeWidget * parent, QTreeWidgetItem * preceding, int type = Type) : QTreeWidgetItem(parent, preceding, type) {}
- CQTreeWidgetItem(QTreeWidgetItem * parent, int type = Type) : QTreeWidgetItem(parent, type) {}
- CQTreeWidgetItem(QTreeWidgetItem * parent, const QStringList & strings, int type = Type) : QTreeWidgetItem(parent, strings, type) {}
- CQTreeWidgetItem(QTreeWidgetItem * parent, QTreeWidgetItem * preceding, int type = Type) : QTreeWidgetItem(parent, preceding, type) {}
- virtual ~CQTreeWidgetItem() {}
- inline virtual bool operator<(const QTreeWidgetItem &tmp) const {
- int column = this->treeWidget()->sortColumn();
- // We are in date text
- if(column == DirWidget::DATEMOD || column == DirWidget::DATECREATE)
- return this->whatsThis(column) < tmp.whatsThis(column);
- // We are in size text
- else if(column == DirWidget::SIZE) {
- QString text = this->text(column);
- QString text_tmp = tmp.text(column);
- double filesize, filesize_tmp;
- // On folders, text is empty so we check for that
- // In case we are in folders, we put -1 for differentiate of regular files with 0 bytes.
- // Doing so, all folders we'll be together instead of mixing with files with 0 bytes.
- if(text.isEmpty())
- filesize = -1;
- else
- filesize = LUtils::DisplaySizeToBytes(text);
- if(text_tmp.isEmpty())
- filesize_tmp = -1;
- else
- filesize_tmp = LUtils::DisplaySizeToBytes(text_tmp);
- return filesize < filesize_tmp;
- }
- // In other cases, we trust base class implementation
- return QTreeWidgetItem::operator<(tmp);
- }
-};
-#endif
diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.ui b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.ui
deleted file mode 100644
index c5bf12c3..00000000
--- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget.ui
+++ /dev/null
@@ -1,527 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>DirWidget</class>
- <widget class="QWidget" name="DirWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>400</width>
- <height>350</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>350</width>
- <height>0</height>
- </size>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0" columnstretch="0,1">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <property name="horizontalSpacing">
- <number>1</number>
- </property>
- <property name="verticalSpacing">
- <number>2</number>
- </property>
- <item row="0" column="0" rowspan="2" colspan="2">
- <layout class="QHBoxLayout" name="toolbar_layout"/>
- </item>
- <item row="3" column="0" colspan="2">
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QToolButton" name="tool_new_file">
- <property name="statusTip">
- <string>Create a new file</string>
- </property>
- <property name="text">
- <string>New File</string>
- </property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonTextBesideIcon</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_new_dir">
- <property name="statusTip">
- <string>Create a new directory</string>
- </property>
- <property name="text">
- <string>New Dir</string>
- </property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonTextBesideIcon</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_goToImages">
- <property name="statusTip">
- <string>Add selected images to slideshow</string>
- </property>
- <property name="text">
- <string>Slideshow</string>
- </property>
- <property name="iconSize">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonTextBesideIcon</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_goToPlayer">
- <property name="statusTip">
- <string>Enqueue selection in multimedia player</string>
- </property>
- <property name="text">
- <string>Play</string>
- </property>
- <property name="iconSize">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonTextBesideIcon</enum>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QLabel" name="label_status">
- <property name="text">
- <string notr="true">Status</string>
- </property>
- <property name="wordWrap">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="2" column="1">
- <layout class="QVBoxLayout" name="browser_layout">
- <property name="spacing">
- <number>1</number>
- </property>
- <item>
- <widget class="QFrame" name="group_snaps">
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <property name="leftMargin">
- <number>1</number>
- </property>
- <property name="topMargin">
- <number>1</number>
- </property>
- <property name="rightMargin">
- <number>1</number>
- </property>
- <property name="bottomMargin">
- <number>1</number>
- </property>
- <item>
- <widget class="QToolButton" name="tool_snap">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="styleSheet">
- <string notr="true">padding-right: 5px;</string>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="popupMode">
- <enum>QToolButton::InstantPopup</enum>
- </property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonTextOnly</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSlider" name="slider_snap">
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="value">
- <number>1</number>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="invertedAppearance">
- <bool>false</bool>
- </property>
- <property name="invertedControls">
- <bool>false</bool>
- </property>
- <property name="tickPosition">
- <enum>QSlider::TicksAbove</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_snap_older">
- <property name="text">
- <string notr="true">...</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_snap_newer">
- <property name="text">
- <string notr="true">...</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </item>
- <item row="2" column="0">
- <widget class="QFrame" name="group_actions">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QToolButton" name="tool_act_run">
- <property name="toolTip">
- <string>Open item</string>
- </property>
- <property name="statusTip">
- <string>Open item</string>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="iconSize">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonIconOnly</enum>
- </property>
- <property name="autoRaise">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_act_runwith">
- <property name="toolTip">
- <string>Open item (select application)</string>
- </property>
- <property name="statusTip">
- <string>Open item (select application)</string>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="iconSize">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- <property name="autoRaise">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="Line" name="line_5">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_act_fav">
- <property name="toolTip">
- <string>Add item to personal favorites</string>
- </property>
- <property name="statusTip">
- <string>Add item to personal favorites</string>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="iconSize">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- <property name="autoRaise">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_act_rename">
- <property name="toolTip">
- <string>Rename item</string>
- </property>
- <property name="statusTip">
- <string>Rename item</string>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="iconSize">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- <property name="autoRaise">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="Line" name="line_7">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_act_cut">
- <property name="toolTip">
- <string>Cut items</string>
- </property>
- <property name="statusTip">
- <string>Cut items (add to the clipboard)</string>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="iconSize">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- <property name="autoRaise">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_act_copy">
- <property name="toolTip">
- <string>Copy items</string>
- </property>
- <property name="statusTip">
- <string>Copy items to the clipboard</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="iconSize">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- <property name="autoRaise">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_act_paste">
- <property name="toolTip">
- <string>Paste items from clipboard</string>
- </property>
- <property name="statusTip">
- <string>Paste items from clipboard</string>
- </property>
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="iconSize">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- <property name="autoRaise">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="Line" name="line_6">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="tool_act_rm">
- <property name="toolTip">
- <string>Delete Items</string>
- </property>
- <property name="statusTip">
- <string>Delete Items</string>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="iconSize">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- <property name="autoRaise">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- <action name="actionBack">
- <property name="text">
- <string notr="true">Back</string>
- </property>
- <property name="iconText">
- <string>Back</string>
- </property>
- <property name="toolTip">
- <string>Go back to previous directory</string>
- </property>
- <property name="statusTip">
- <string>Go back to previous directory</string>
- </property>
- </action>
- <action name="actionUp">
- <property name="text">
- <string notr="true">Up</string>
- </property>
- <property name="iconText">
- <string>Up</string>
- </property>
- <property name="toolTip">
- <string>Go to parent directory</string>
- </property>
- <property name="statusTip">
- <string>Go to parent directory</string>
- </property>
- </action>
- <action name="actionHome">
- <property name="text">
- <string notr="true">Home</string>
- </property>
- <property name="iconText">
- <string>Home</string>
- </property>
- <property name="toolTip">
- <string>Go to home directory</string>
- </property>
- <property name="statusTip">
- <string>Go to home directory</string>
- </property>
- </action>
- <action name="actionStopLoad">
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="statusTip">
- <string>Stop loading the directory</string>
- </property>
- </action>
- <action name="actionClose_Browser">
- <property name="text">
- <string notr="true">Close Browser</string>
- </property>
- <property name="iconText">
- <string notr="true">Close Browser</string>
- </property>
- <property name="toolTip">
- <string>Close this browser</string>
- </property>
- <property name="statusTip">
- <string>Close this browser</string>
- </property>
- </action>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp
new file mode 100644
index 00000000..48ad6aa5
--- /dev/null
+++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp
@@ -0,0 +1,734 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "DirWidget2.h"
+#include "ui_DirWidget2.h"
+
+#include <QMessageBox>
+#include <QCursor>
+#include <QClipboard>
+#include <QMimeData>
+#include <QTimer>
+#include <QInputDialog>
+#include <QScrollBar>
+#include <QSettings>
+#include <QtConcurrent/QtConcurrentRun>
+
+#include <LuminaOS.h>
+#include <LuminaXDG.h>
+#include <LUtils.h>
+
+#include "../ScrollDialog.h"
+
+#define DEBUG 0
+
+DirWidget::DirWidget(QString objID, QWidget *parent) : QWidget(parent), ui(new Ui::DirWidget){
+ ui->setupUi(this); //load the designer file
+ ID = objID;
+ //Assemble the toolbar for the widget
+ toolbar = new QToolBar(this);
+ toolbar->setContextMenuPolicy(Qt::CustomContextMenu);
+ toolbar->setFloatable(false);
+ toolbar->setMovable(false);
+ toolbar->setOrientation(Qt::Horizontal);
+ toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly);
+ //toolbar->setIconSize(QSize(32,32));
+ ui->toolbar_layout->addWidget(toolbar);
+ // - Add the buttons to the toolbar
+ toolbar->addAction(ui->actionBack);
+ toolbar->addAction(ui->actionUp);
+ toolbar->addAction(ui->actionHome);
+ line_dir = new QLineEdit(this);
+ toolbar->addWidget(line_dir);
+ connect(line_dir, SIGNAL(returnPressed()), this, SLOT(dir_changed()) );
+ toolbar->addAction(ui->actionSingleColumn);
+ ui->actionSingleColumn->setChecked(true);
+ toolbar->addAction(ui->actionDualColumn);
+ toolbar->addAction(ui->actionMenu);
+ //Add the browser widgets
+ RCBW = 0; //right column browser is unavailable initially
+ BW = new BrowserWidget("", this);
+ ui->browser_layout->addWidget(BW);
+ connect(BW, SIGNAL(dirChange(QString)), this, SLOT(currentDirectoryChanged()) );
+ connect(BW, SIGNAL(itemsActivated()), this, SLOT(runFiles()) );
+ connect(BW, SIGNAL(DataDropped(QString, QStringList)), this, SIGNAL(PasteFiles(QString, QStringList)) );
+ connect(BW, SIGNAL(contextMenuRequested()), this, SLOT(OpenContextMenu()) );
+ connect(BW, SIGNAL(updateDirectoryStatus(QString)), this, SLOT(dirStatusChanged(QString)) );
+ connect(BW, SIGNAL(hasFocus(QString)), this, SLOT(setCurrentBrowser(QString)) );
+ //Now update the rest of the UI
+ canmodify = false; //initial value
+ contextMenu = new QMenu(this);
+ cNewMenu = cOpenMenu = cFModMenu = cFViewMenu = 0; //not created yet
+ connect(contextMenu, SIGNAL(aboutToShow()), this, SLOT(UpdateContextMenu()) );
+
+ UpdateIcons();
+ UpdateText();
+ createShortcuts();
+ createMenus();
+}
+
+DirWidget::~DirWidget(){
+ //stopload = true; //just in case another thread is still loading/running
+}
+
+void DirWidget::setFocusLineDir() {
+ line_dir->setFocus();
+ line_dir->selectAll();
+}
+
+void DirWidget::cleanup(){
+ //stopload = true; //just in case another thread is still loading/running
+ //if(thumbThread.isRunning()){ thumbThread.waitForFinished(); } //this will stop really quickly with the flag set
+}
+
+void DirWidget::ChangeDir(QString dirpath){
+ //stopload = true; //just in case it is still loading
+ //emit LoadDirectory(ID, dirpath);
+ //qDebug() << "ChangeDir:" << dirpath;
+ currentBrowser()->changeDirectory(dirpath);
+}
+
+void DirWidget::setDirCompleter(QCompleter *comp){
+ //line_dir->setCompleter(comp);
+}
+
+QString DirWidget::id(){
+ return ID;
+}
+
+QString DirWidget::currentDir(){
+ return currentBrowser()->currentDirectory();
+}
+
+void DirWidget::setShowDetails(bool show){
+ BW->showDetails(show);
+ if(RCBW!=0){ RCBW->showDetails(show); }
+}
+
+void DirWidget::showHidden(bool show){
+ BW->showHiddenFiles(show);
+ if(RCBW!=0){ RCBW->showHiddenFiles(show); }
+}
+
+void DirWidget::setThumbnailSize(int px){
+ BW->setThumbnailSize(px);
+ if(RCBW!=0){ RCBW->setThumbnailSize(px); }
+ ui->tool_zoom_in->setEnabled(px < 256); //upper limit on image sizes
+ ui->tool_zoom_out->setEnabled(px >16); //lower limit on image sizes
+}
+
+// ================
+// PUBLIC SLOTS
+// ================
+
+void DirWidget::LoadSnaps(QString basedir, QStringList snaps){
+ //Save these value internally for use later
+ //qDebug() << "ZFS Snapshots available:" << basedir << snaps;
+ snapbasedir = basedir;
+ snapshots = snaps;
+ //if(!snapbasedir.isEmpty()){ watcher->addPath(snapbasedir); } //add this to the watcher in case snapshots get created/removed
+ //Now update the UI as necessary
+ if(ui->tool_snap->menu()==0){
+ ui->tool_snap->setMenu(new QMenu(this));
+ connect(ui->tool_snap->menu(), SIGNAL(triggered(QAction*)), this, SLOT(direct_snap_selected(QAction*)) );
+ }
+ ui->tool_snap->menu()->clear();
+ for(int i=0; i<snapshots.length(); i++){
+ QAction *tmp = ui->tool_snap->menu()->addAction(snapshots[i]);
+ tmp->setWhatsThis(snapshots[i]);
+ }
+ ui->slider_snap->setRange(0, snaps.length());
+ if(currentBrowser()->currentDirectory().contains(ZSNAPDIR)){
+ //The user was already within a snapshot - figure out which one and set the slider appropriately
+ int index = snaps.indexOf( currentBrowser()->currentDirectory().section(ZSNAPDIR,1,1).section("/",0,0) );
+ if(index < 0){ index = snaps.length(); } //unknown - load the system (should never happen)
+ ui->slider_snap->setValue(index);
+ }else{
+ ui->slider_snap->setValue(snaps.length()); //last item (normal system)
+ }
+ on_slider_snap_valueChanged();
+ QApplication::processEvents(); //let the slider changed signal get thrown away before we re-enable the widget
+ ui->group_snaps->setEnabled(!snaps.isEmpty());
+ ui->group_snaps->setVisible(!snaps.isEmpty());
+ ui->tool_snap_newer->setEnabled(ui->slider_snap->value() < ui->slider_snap->maximum());
+ ui->tool_snap_older->setEnabled(ui->slider_snap->value() > ui->slider_snap->minimum());
+}
+
+void DirWidget::refresh(){
+ currentBrowser()->changeDirectory(""); //refresh current dir
+}
+
+//Theme change functions
+void DirWidget::UpdateIcons(){
+ //Snapshot buttons
+ ui->tool_snap_newer->setIcon(LXDG::findIcon("go-next-view","") );
+ ui->tool_snap_older->setIcon(LXDG::findIcon("go-previous-view","") );
+
+ //ToolBar Buttons
+ ui->actionBack->setIcon( LXDG::findIcon("go-previous","") );
+ ui->actionUp->setIcon( LXDG::findIcon("go-up","") );
+ ui->actionHome->setIcon( LXDG::findIcon("go-home","") );
+ ui->actionMenu->setIcon( LXDG::findIcon("format-justify-fill","format-list-unordered") );
+ ui->actionSingleColumn->setIcon(LXDG::findIcon("view-right-close","view-close") );
+ ui->actionDualColumn->setIcon(LXDG::findIcon("view-right-new","view-split-left-right") );
+
+ ui->tool_zoom_in->setIcon(LXDG::findIcon("zoom-in",""));
+ ui->tool_zoom_out->setIcon(LXDG::findIcon("zoom-out",""));
+
+}
+
+void DirWidget::UpdateText(){
+ ui->retranslateUi(this);
+ BW->retranslate();
+ if(RCBW!=0){ RCBW->retranslate(); }
+}
+
+// =================
+// PRIVATE
+// =================
+void DirWidget::createShortcuts(){
+kZoomIn= new QShortcut(QKeySequence(QKeySequence::ZoomIn),this);
+kZoomOut= new QShortcut(QKeySequence(QKeySequence::ZoomOut),this);
+kNewFile= new QShortcut(QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_F),this);
+kNewDir= new QShortcut(QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_N),this);
+kNewXDG= new QShortcut(QKeySequence(Qt::CTRL+Qt::Key_G),this);
+kCut= new QShortcut(QKeySequence(QKeySequence::Cut),this);
+kCopy= new QShortcut(QKeySequence(QKeySequence::Copy),this);
+kPaste= new QShortcut(QKeySequence(QKeySequence::Paste),this);
+kRename= new QShortcut(QKeySequence(Qt::Key_F2),this);
+kFav= new QShortcut(QKeySequence(Qt::Key_F3),this);
+kDel= new QShortcut(QKeySequence(QKeySequence::Delete),this);
+kOpSS= new QShortcut(QKeySequence(Qt::Key_F6),this);
+kOpMM= new QShortcut(QKeySequence(Qt::Key_F7),this);
+kOpTerm = new QShortcut(QKeySequence(Qt::Key_F1),this);
+
+connect(kZoomIn, SIGNAL(activated()), this, SLOT(on_tool_zoom_in_clicked()) );
+connect(kZoomOut, SIGNAL(activated()), this, SLOT(on_tool_zoom_out_clicked()) );
+connect(kNewFile, SIGNAL(activated()), this, SLOT(createNewFile()) );
+connect(kNewDir, SIGNAL(activated()), this, SLOT(createNewDir()) );
+connect(kNewXDG, SIGNAL(activated()), this, SLOT(createNewXDGEntry()) );
+connect(kCut, SIGNAL(activated()), this, SLOT(cutFiles()) );
+connect(kCopy, SIGNAL(activated()), this, SLOT(copyFiles()) );
+connect(kPaste, SIGNAL(activated()), this, SLOT(pasteFiles()) );
+connect(kRename, SIGNAL(activated()), this, SLOT(renameFiles()) );
+connect(kFav, SIGNAL(activated()), this, SLOT(favoriteFiles()) );
+connect(kDel, SIGNAL(activated()), this, SLOT(removeFiles()) );
+connect(kOpSS, SIGNAL(activated()), this, SLOT(openInSlideshow()) );
+connect(kOpMM, SIGNAL(activated()), this, SLOT(openMultimedia()) );
+connect(kOpTerm, SIGNAL(activated()), this, SLOT(openTerminal()) );
+
+}
+
+void DirWidget::createMenus(){
+ //Note: contextMenu already created - this is just for the sub-items
+ if(cNewMenu==0){ cNewMenu = new QMenu(this); }
+ else{ cNewMenu->clear(); }
+ cNewMenu->setTitle(tr("Create...") );
+ cNewMenu->setIcon( LXDG::findIcon("list-add","") );
+ cNewMenu->addAction(LXDG::findIcon("document-new",""), tr("File"), this, SLOT(createNewFile()), kNewFile->key() );
+ cNewMenu->addAction(LXDG::findIcon("folder-new",""), tr("Directory"), this, SLOT(createNewDir()), kNewDir->key() );
+ if(LUtils::isValidBinary("lumina-fileinfo")){ cNewMenu->addAction(LXDG::findIcon("system-run",""), tr("Application Launcher"), this, SLOT(createNewXDGEntry()), kNewXDG->key() ); }
+
+ if(cOpenMenu==0){ cOpenMenu = new QMenu(this); }
+ else{ cOpenMenu->clear(); }
+ cOpenMenu->setTitle(tr("Launch..."));
+ cOpenMenu->setIcon( LXDG::findIcon("quickopen","") );
+ cOpenMenu->addAction(LXDG::findIcon("utilities-terminal",""), tr("Terminal"), this, SLOT(openTerminal()), kOpTerm->key());
+ cOpenMenu->addAction(LXDG::findIcon("view-preview",""), tr("SlideShow"), this, SLOT(openInSlideshow()), kOpSS->key());
+ cOpenMenu->addAction(LXDG::findIcon("view-media-lyrics","media-playback-start"), tr("Multimedia Player"), this, SLOT(openMultimedia()), kOpMM->key());
+
+ if(cFModMenu==0){ cFModMenu = new QMenu(this); }
+ else{ cFModMenu->clear(); }
+ cFModMenu->setTitle(tr("Modify Files..."));
+ cFModMenu->setIcon( LXDG::findIcon("document-edit","") );
+ cFModMenu->addAction(LXDG::findIcon("edit-cut",""), tr("Cut Selection"), this, SLOT(cutFiles()), kCut->key() );
+ cFModMenu->addAction(LXDG::findIcon("edit-copy",""), tr("Copy Selection"), this, SLOT(copyFiles()), kCopy->key() );
+ cFModMenu->addSeparator();
+ cFModMenu->addAction(LXDG::findIcon("edit-rename",""), tr("Rename..."), this, SLOT(renameFiles()), kRename->key() );
+ cFModMenu->addSeparator();
+ cFModMenu->addAction(LXDG::findIcon("edit-delete",""), tr("Delete Selection"), this, SLOT(removeFiles()), kDel->key() );
+
+ if(cFViewMenu==0){ cFViewMenu = new QMenu(this); }
+ else{ cFViewMenu->clear(); }
+ cFViewMenu->setTitle(tr("View Files..."));
+ cFViewMenu->setIcon( LXDG::findIcon("document-preview","") );
+ cFViewMenu->addAction(LXDG::findIcon("document-encrypted",""), tr("Checksums"), this, SLOT(fileCheckSums()) );
+ if(LUtils::isValidBinary("lumina-fileinfo")){
+ cFViewMenu->addAction(LXDG::findIcon("edit-find-replace",""), tr("Properties"), this, SLOT(fileProperties()) );
+ }
+
+}
+
+BrowserWidget* DirWidget::currentBrowser(){
+ if(cBID.isEmpty() || RCBW==0){ return BW; }
+ else{ return RCBW; }
+}
+
+QStringList DirWidget::currentDirFiles(){
+ return currentBrowser()->currentItems(-1); //files only
+}
+// =================
+// PRIVATE SLOTS
+// =================
+
+//UI BUTTONS
+void DirWidget::on_tool_zoom_in_clicked(){
+ int size = BW->thumbnailSize();
+ size += 16;
+ setThumbnailSize(size);
+ //Now Save the size value as the default for next time
+ QSettings SET("lumina-desktop","lumina-fm");
+ SET.setValue("iconsize", size);
+}
+
+void DirWidget::on_tool_zoom_out_clicked(){
+ int size = BW->thumbnailSize();
+ if(size <= 16){ return; }
+ size -= 16;
+ setThumbnailSize(size);
+ //Now Save the size value as the default for next time
+ QSettings SET("lumina-desktop","lumina-fm");
+ SET.setValue("iconsize", size);
+}
+
+// -- Top Snapshot Buttons
+void DirWidget::on_tool_snap_newer_clicked(){
+ ui->slider_snap->setValue( ui->slider_snap->value()+1 );
+}
+
+void DirWidget::on_tool_snap_older_clicked(){
+ ui->slider_snap->setValue( ui->slider_snap->value()-1 );
+}
+
+void DirWidget::on_slider_snap_valueChanged(int val){
+ bool labelsonly = false;
+ if(val==-1){ val = ui->slider_snap->value(); labelsonly=true; }
+ //Update the snapshot interface
+ ui->tool_snap_newer->setEnabled(val < ui->slider_snap->maximum());
+ ui->tool_snap_older->setEnabled(val > ui->slider_snap->minimum());
+ if(val >= snapshots.length() || val < 0){
+ ui->tool_snap->setText(tr("Current"));
+ }else if(QFile::exists(snapbasedir+snapshots[val])){
+ ui->tool_snap->setText( QFileInfo(snapbasedir+snapshots[val]).lastModified().toString(Qt::DefaultLocaleShortDate) );
+ }
+ //Exit if a non-interactive snapshot change
+ if(!ui->group_snaps->isEnabled() || labelsonly){ return; } //internal change - do not try to change the actual info
+ //Determine which snapshot is now selected
+ QString dir;
+ if(DEBUG){ qDebug() << "Changing snapshot:" << currentBrowser()->currentDirectory() << val << snapbasedir; }
+ //stopload = true; //stop any currently-loading procedures
+ if(val >= snapshots.length() || val < 0){ //active system selected
+ if(DEBUG){ qDebug() << " - Load Active system:" << normalbasedir; }
+ dir = normalbasedir;
+ }else{
+ dir = snapbasedir+snapshots[val]+"/";
+ if(!QFile::exists(dir)){
+ //This snapshot must have been removed in the background by pruning tools
+ // move to a newer snapshot or the current base dir as necessary
+ qDebug() << "Snapshot no longer available:" << dir;
+ qDebug() << " - Reloading available snapshots";
+ emit findSnaps(ID, normalbasedir);
+ return;
+ }
+ //Need to figure out the relative path within the snapshot
+ snaprelpath = normalbasedir.section(snapbasedir.section(ZSNAPDIR,0,0), 1,1000);
+ if(DEBUG){ qDebug() << " - new snapshot-relative path:" << snaprelpath; }
+ dir.append(snaprelpath);
+ dir.replace("//","/"); //just in case any duplicate slashes from all the split/combining
+ if(DEBUG){ qDebug() << " - Load Snapshot:" << dir; }
+ }
+ //Make sure this directory exists, and back up as necessary
+ if(dir.isEmpty()){ return; }
+ //Load the newly selected snapshot
+ currentBrowser()->changeDirectory(dir);
+}
+
+void DirWidget::direct_snap_selected(QAction *act){
+ QString snap = act->whatsThis();
+ int val = snapshots.indexOf(snap);
+ if(val<0){ return; }
+ else{ ui->slider_snap->setValue(val); }
+}
+
+//Top Toolbar buttons
+void DirWidget::on_actionBack_triggered(){
+ QStringList history = currentBrowser()->history();
+ if(history.length()<2){ return; } //cannot do anything
+ QString dir = history.takeLast();
+ //qDebug() << "Go Back:" << dir << normalbasedir << history;
+ if(dir == normalbasedir){
+ dir = history.takeLast();
+ }
+ history << dir; //make sure the current dir is always last in the history
+ currentBrowser()->changeDirectory(dir);
+ currentBrowser()->setHistory(history); //re-write the history to account for going backwards
+ ui->actionBack->setEnabled(history.length()>1);
+}
+
+void DirWidget::on_actionUp_triggered(){
+ QString dir = currentBrowser()->currentDirectory().section("/",0,-2);
+ if(dir.isEmpty())
+ dir = "/";
+ //Quick check to ensure the directory exists
+ while(!QFile::exists(dir) && !dir.isEmpty()){
+ dir = dir.section("/",0,-2); //back up one additional dir
+ }
+ currentBrowser()->changeDirectory(dir);
+}
+
+void DirWidget::on_actionHome_triggered(){
+ currentBrowser()->changeDirectory(QDir::homePath());
+}
+
+void DirWidget::dir_changed(){
+ QString dir = line_dir->text().simplified();
+ //Run the dir through the user-input checks
+ dir = LUtils::PathToAbsolute(dir);
+ //qDebug() << "Dir Changed:" << dir;
+ //Quick check to ensure the directory exists
+ while(!QFile::exists(dir) && !dir.isEmpty()){
+ dir = dir.section("/",0,-2); //back up one additional dir
+ }
+ //qDebug() << " - Now Dir:" << dir;
+ currentBrowser()->changeDirectory(dir);
+ //emit LoadDirectory(ID, dir);
+}
+
+
+void DirWidget::on_actionSingleColumn_triggered(bool checked){
+ if(!checked){ return; }
+ ui->actionDualColumn->setChecked(false);
+ if(RCBW==0){ return; } //nothing to do
+ ui->browser_layout->removeWidget(RCBW);
+ RCBW->deleteLater();
+ RCBW = 0;
+ setCurrentBrowser(""); //reset back to the remaining browser
+}
+
+void DirWidget::on_actionDualColumn_triggered(bool checked){
+ if(!checked){ return; }
+ ui->actionSingleColumn->setChecked(false);
+ if(RCBW!=0){ return; } //nothing to do
+ RCBW = new BrowserWidget("rc", this);
+ ui->browser_layout->addWidget(RCBW);
+ connect(RCBW, SIGNAL(dirChange(QString)), this, SLOT(currentDirectoryChanged()) );
+ connect(RCBW, SIGNAL(itemsActivated()), this, SLOT(runFiles()) );
+ connect(RCBW, SIGNAL(DataDropped(QString, QStringList)), this, SIGNAL(PasteFiles(QString, QStringList)) );
+ connect(RCBW, SIGNAL(contextMenuRequested()), this, SLOT(OpenContextMenu()) );
+ connect(RCBW, SIGNAL(updateDirectoryStatus(QString)), this, SLOT(dirStatusChanged(QString)) );
+ connect(RCBW, SIGNAL(hasFocus(QString)), this, SLOT(setCurrentBrowser(QString)) );
+ //Now make sure it has all the same settings as the main browser
+ setCurrentBrowser("rc");
+ RCBW->showDetails(BW->hasDetails());
+ RCBW->showHiddenFiles( BW->hasHiddenFiles());
+ RCBW->setThumbnailSize( BW->thumbnailSize());
+ RCBW->changeDirectory( BW->currentDirectory());
+}
+
+void DirWidget::on_actionMenu_triggered(){
+ OpenContextMenu();
+}
+
+
+// - Other Actions without a specific button on the side
+void DirWidget::fileCheckSums(){
+ QStringList files = currentBrowser()->currentSelection();
+ if(files.isEmpty()){ return; }
+ qDebug() << "Run Checksums:" << files;
+ QStringList info = LOS::Checksums(files);
+ qDebug() << " - Info:" << info;
+ if(info.isEmpty() || (info.length() != files.length()) ){ return; }
+ for(int i=0; i<info.length(); i++){
+ info[i] = QString("%2\n\t(%1)").arg(files[i].section("/",-1), info[i]);
+ }
+ ScrollDialog dlg(this);
+ dlg.setWindowTitle( tr("File Checksums:") );
+ dlg.setWindowIcon( LXDG::findIcon("document-encrypted","") );
+ dlg.setText(info.join("\n"));
+ dlg.exec();
+}
+
+void DirWidget::fileProperties(){
+ QStringList sel = currentBrowser()->currentSelection();
+ //qDebug() << "Open File properties:" << sel;
+ if(sel.isEmpty()){ return; }
+ if(!LUtils::isValidBinary("lumina-fileinfo")){
+ //It should never get to this point due to checks earlier - but just in case...
+ QMessageBox::warning(this, tr("Missing Utility"), tr("The \"lumina-fileinfo\" utility could not be found on the system. Please install it first.") );
+ return;
+ }
+ for(int i=0; i<sel.length(); i++){
+ QProcess::startDetached("lumina-fileinfo \""+sel[i]+"\""); //use absolute paths
+ }
+}
+
+void DirWidget::openTerminal(){
+ emit LaunchTerminal(currentBrowser()->currentDirectory());
+}
+
+//Browser Functions
+void DirWidget::OpenContextMenu(){
+ //Now open the menu at the current cursor location
+ contextMenu->popup(QCursor::pos());
+}
+
+void DirWidget::UpdateContextMenu(){
+ //First generate the context menu based on the selection
+ //qDebug() << "Update context menu";
+ QStringList sel = currentBrowser()->currentSelection();
+ contextMenu->clear();
+
+ if(!sel.isEmpty()){
+ contextMenu->addAction(LXDG::findIcon("run-build-file",""), tr("Open"), this, SLOT(runFiles()) );
+ contextMenu->addAction(LXDG::findIcon("run-build-configure",""), tr("Open With..."), this, SLOT(runWithFiles()) );
+ }
+ contextMenu->addSection(LXDG::findIcon("unknown",""), tr("File Operations"));
+ contextMenu->addMenu(cFModMenu);
+ cFModMenu->setEnabled(!sel.isEmpty() && canmodify);
+ contextMenu->addMenu(cFViewMenu);
+ cFViewMenu->setEnabled(!sel.isEmpty());
+ contextMenu->addAction(LXDG::findIcon("edit-paste",""), tr("Paste"), this, SLOT(pasteFiles()), QKeySequence(Qt::CTRL+Qt::Key_V) )->setEnabled(QApplication::clipboard()->mimeData()->hasFormat("x-special/lumina-copied-files") && canmodify);
+ //Now add the general selection options
+ contextMenu->addSection(LXDG::findIcon("folder","inode/directory"), tr("Directory Operations"));
+ if(canmodify){
+ contextMenu->addMenu(cNewMenu);
+ }
+ contextMenu->addMenu(cOpenMenu);
+}
+
+void DirWidget::currentDirectoryChanged(bool widgetonly){
+ QString cur = currentBrowser()->currentDirectory();
+ QFileInfo info(cur);
+ canmodify = info.isWritable();
+ if(widgetonly){ ui->label_status->setText(currentBrowser()->status()); }
+ else if( !currentBrowser()->isEnabled() ){ ui->label_status->setText(tr("Loading...")); }
+ //qDebug() << "Start search for snapshots";
+ if(!cur.contains("/.zfs/snapshot") ){
+ normalbasedir = cur;
+ ui->group_snaps->setVisible(false);
+ emit findSnaps(ID, cur);
+ qDebug() << "Changed to directory:" << cur;
+ }else{
+ //Re-assemble the normalbasedir variable (in case moving around within a snapshot)
+ normalbasedir = cur;
+ normalbasedir.replace( QRegExp("\\/\\.zfs\\/snapshot/([^/]+)\\/"), "/" );
+ qDebug() << "Changed to snapshot:" << cur << normalbasedir;
+ }
+ ui->actionBack->setEnabled( currentBrowser()->history().length()>1 );
+ line_dir->setText(normalbasedir);
+ emit TabNameChanged(ID, normalbasedir.section("/",-1));
+}
+
+void DirWidget::dirStatusChanged(QString stat){
+ if(!canmodify){ stat.prepend(tr("(Limited Access) ")); }
+ ui->label_status->setText(stat);
+}
+
+void DirWidget::setCurrentBrowser(QString id){
+ //qDebug() << "Set Current Browser:" << id;
+ if(id==cBID){ return; } //no change
+ cBID = id;
+ currentDirectoryChanged(true); //update all the averarching widget elements (widget only)
+ //Now adjust the frame/highlighting around the "active" browser
+ if(RCBW==0){ BW->setShowActive(true); }
+ else{
+ BW->setShowActive( cBID.isEmpty() );
+ RCBW->setShowActive( !cBID.isEmpty() );
+ }
+}
+
+//Context Menu Functions
+void DirWidget::createNewFile(){
+ if(!canmodify){ return; } //cannot create anything here
+ //Prompt for the new filename
+ bool ok = false;
+ QString newdocument = QInputDialog::getText(this, tr("New Document"), tr("Name:"), QLineEdit::Normal, "", \
+ &ok, 0, Qt::ImhFormattedNumbersOnly | Qt::ImhUppercaseOnly | Qt::ImhLowercaseOnly);
+ if(!ok || newdocument.isEmpty()){ return; }
+ //Create the empty file
+ QString full = currentBrowser()->currentDirectory();
+ if(!full.endsWith("/")){ full.append("/"); }
+ //verify the new file does not already exist
+ if(QFile::exists(full+newdocument)){
+ QMessageBox::warning(this, tr("Invalid Name"), tr("A file or directory with that name already exists! Please pick a different name."));
+ QTimer::singleShot(0,this, SLOT(createNewFile()) ); //repeat this function
+ return;
+ }
+ QFile file(full+newdocument);
+ if(file.open(QIODevice::ReadWrite)){
+ //If successfully opened, it has created a blank file
+ file.close();
+ }else{
+ QMessageBox::warning(this, tr("Error Creating Document"), tr("The document could not be created. Please ensure that you have the proper permissions."));
+ }
+}
+
+void DirWidget::createNewDir(){
+ if(!canmodify){ return; } //cannot create anything here
+ //Prompt for the new dir name
+ bool ok = false;
+ QString newdir = QInputDialog::getText(this, tr("New Directory"), tr("Name:"), QLineEdit::Normal, "", \
+ &ok, 0, Qt::ImhFormattedNumbersOnly | Qt::ImhUppercaseOnly | Qt::ImhLowercaseOnly);
+ if(!ok || newdir.isEmpty()){ return; }
+ //Now create the new dir
+ QString full = currentBrowser()->currentDirectory();
+ if(!full.endsWith("/")){ full.append("/"); }
+ QDir dir(full); //open the current dir
+ full.append(newdir); //append the new name to the current dir
+ //Verify that the new dir does not already exist
+ if(dir.exists(full)){
+ QMessageBox::warning(this, tr("Invalid Name"), tr("A file or directory with that name already exists! Please pick a different name."));
+ QTimer::singleShot(0,this, SLOT(createNewDir()) ); //repeat this function
+ }else{
+ if(!dir.mkdir(newdir) ){
+ QMessageBox::warning(this, tr("Error Creating Directory"), tr("The directory could not be created. Please ensure that you have the proper permissions to modify the current directory."));
+ }
+ }
+}
+
+void DirWidget::createNewXDGEntry(){
+ if(!canmodify){ return; } //cannot create anything here
+ //Prompt for the new filename
+ bool ok = false;
+ QString newdocument = QInputDialog::getText(this, tr("New Document"), tr("Name:"), QLineEdit::Normal, "", \
+ &ok, 0, Qt::ImhFormattedNumbersOnly | Qt::ImhUppercaseOnly | Qt::ImhLowercaseOnly);
+ if(!ok || newdocument.isEmpty()){ return; }
+ if(!newdocument.endsWith(".desktop")){ newdocument.append(".desktop"); }
+ //Create the empty file
+ QString full = currentBrowser()->currentDirectory();
+ if(!full.endsWith("/")){ full.append("/"); }
+ //Verify the file does not already exist
+ if(QFile::exists(full+newdocument)){
+ QMessageBox::warning(this, tr("Invalid Name"), tr("A file or directory with that name already exists! Please pick a different name."));
+ QTimer::singleShot(0,this, SLOT(createNewFile()) ); //repeat this function
+ return;
+ }
+ QProcess::startDetached("lumina-fileinfo -application \""+full+newdocument+"\"");
+}
+
+/*void DirWidget::createNewSymlink{
+
+}*/
+
+// - Selected FILE operations
+void DirWidget::cutFiles(){
+ QStringList sel = currentBrowser()->currentSelection();
+ if(sel.isEmpty() || !canmodify){ return; }
+ emit CutFiles(sel);
+}
+
+void DirWidget::copyFiles(){
+ QStringList sel = currentBrowser()->currentSelection();
+ if(sel.isEmpty()){ return; }
+ emit CopyFiles(sel);
+}
+
+void DirWidget::pasteFiles(){
+ if( !canmodify ){ return; }
+ emit PasteFiles(currentBrowser()->currentDirectory(), QStringList() );
+}
+
+void DirWidget::renameFiles(){
+ QStringList sel = currentBrowser()->currentSelection();
+ if(sel.isEmpty() || !canmodify){ return; }
+ qDebug() << "Deleting selected Items:" << sel;
+ emit RenameFiles(sel);
+}
+
+void DirWidget::favoriteFiles(){
+ QStringList sel = currentBrowser()->currentSelection();
+ if(sel.isEmpty()){ return; }
+ emit FavoriteFiles(sel);
+}
+
+void DirWidget::removeFiles(){
+ QStringList sel = currentBrowser()->currentSelection();
+ if(sel.isEmpty() || !canmodify){ return; }
+ qDebug() << "Deleting selected Items:" << sel;
+ emit RemoveFiles(sel);
+}
+
+void DirWidget::runFiles(){
+ QStringList sel = currentBrowser()->currentSelection();
+ if(sel.isEmpty()){ return; }
+ QStringList dirs;
+ for(int i=0; i<sel.length(); i++){
+ if(QFileInfo(sel[i]).isDir()){
+ dirs << sel[i];
+ }else{
+ QProcess::startDetached("lumina-open \""+sel[i]+"\"");
+ }
+ }
+ if(!dirs.isEmpty()){
+ currentBrowser()->changeDirectory( dirs.takeFirst()); //load the first directory in this widget
+ }
+ if(!dirs.isEmpty()){
+ emit OpenDirectories(dirs); //open the rest of the directories in other tabs
+ }
+}
+
+void DirWidget::runWithFiles(){
+ QStringList sel = currentBrowser()->currentSelection();
+ if(sel.isEmpty()){ return; }
+ QStringList dirs;
+ for(int i=0; i<sel.length(); i++){
+ if(QFileInfo(sel[i]).isDir()){
+ dirs << sel[i];
+ }else{
+ QProcess::startDetached("lumina-open -select \""+sel[i]+"\"");
+ }
+ }
+ if(!dirs.isEmpty()){
+ emit OpenDirectories(dirs); //open the rest of the directories in other tabs
+ }
+}
+
+/*void DirWidget::attachToNewEmail(){
+
+}*/
+
+// - Context-specific operations
+void DirWidget::openInSlideshow(){
+ QStringList sel = currentBrowser()->currentSelection();
+ if(sel.isEmpty()){ sel = currentDirFiles(); }
+ //Now turn them all into a list and emit them
+ LFileInfoList list;
+ for(int i=0; i<sel.length(); i++){
+ if(sel.endsWith(".desktop")){ continue; } //simplification to make sure we don't read any files which are not needed
+ LFileInfo info(sel[i]);
+ if( info.isImage() ){ list << info; } //add to the list
+ }
+ if(!list.isEmpty()){ emit ViewFiles(list); }
+}
+
+void DirWidget::openMultimedia(){
+ QStringList sel = currentBrowser()->currentSelection();
+ if(sel.isEmpty()){ sel = currentDirFiles(); }
+ //Now turn them all into a list and emit them
+ LFileInfoList list;
+ for(int i=0; i<sel.length(); i++){
+ if(sel.endsWith(".desktop")){ continue; } //simplification to make sure we don't read any files which are not needed
+ LFileInfo info(sel[i]);
+ if( info.isAVFile() ){ list << info; } //add to the list
+ }
+ if(!list.isEmpty()){ emit PlayFiles(list); }
+}
+
+//====================
+// PROTECTED
+//====================
+void DirWidget::mouseReleaseEvent(QMouseEvent *ev){
+ static Qt::MouseButtons backmap = Qt::BackButton | Qt::ExtraButton5;
+ //qDebug() << "Mouse Click:" << ev->button();
+ if(backmap.testFlag(ev->button())){
+ ev->accept();
+ on_actionBack_triggered();
+ //}else if(ev->button()==Qt::ForwardButton()){
+ //ev->accept();
+ }else{
+ ev->ignore(); //not handled here
+ }
+}
diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.h b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.h
new file mode 100644
index 00000000..38e7a657
--- /dev/null
+++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.h
@@ -0,0 +1,173 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_FM_DIRECTORY_BROWSER_WIDGET_H
+#define _LUMINA_FM_DIRECTORY_BROWSER_WIDGET_H
+
+#include <QList>
+#include <QWidget>
+#include <QObject>
+#include <QMenu>
+#include <QToolBar>
+#include <QLineEdit>
+#include <QShortcut>
+#include <QFileSystemWatcher>
+#include <QTimer>
+#include <QFuture>
+
+#include "../BrowserWidget.h"
+
+
+#define ZSNAPDIR QString("/.zfs/snapshot/")
+
+namespace Ui{
+ class DirWidget;
+};
+
+class DirWidget : public QWidget{
+ Q_OBJECT
+public:
+ enum DETAILTYPES{ NAME, SIZE, TYPE, DATEMOD, DATECREATE};
+ DirWidget(QString objID, QWidget *parent = 0); //needs a unique ID (to distinguish from other DirWidgets)
+ ~DirWidget();
+
+ void cleanup(); //called before the browser is closed down
+
+ //Directory Managment
+ void ChangeDir(QString dirpath);
+ void setDirCompleter(QCompleter *comp);
+
+ //Information
+ QString id();
+ QString currentDir();
+
+ //View Settings
+ void setShowDetails(bool show);
+ void showHidden(bool show);
+ void setThumbnailSize(int px);
+ void setFocusLineDir();
+
+public slots:
+ //void LoadDir(QString dir, LFileInfoList list);
+ void LoadSnaps(QString basedir, QStringList snaps);
+
+ //Refresh options
+ void refresh(); //Refresh current directory
+
+ //Theme change functions
+ void UpdateIcons();
+ void UpdateText();
+
+
+private:
+ Ui::DirWidget *ui;
+ BrowserWidget *BW, *RCBW; //Main BrowserWidget and right-column browser widget
+ QString ID, cBID; //unique ID assigned by the parent, and currently active browser widget
+ QString normalbasedir, snapbasedir, snaprelpath; //for maintaining directory context while moving between snapshots
+ QStringList snapshots, needThumbs, tmpSel;
+ bool canmodify;
+
+ //The Toolbar and associated items
+ QToolBar *toolbar;
+ QLineEdit *line_dir;
+
+ //The context menu and associated items
+ QMenu *contextMenu, *cNewMenu, *cOpenMenu, *cFModMenu, *cFViewMenu;
+
+ //The keyboard shortcuts for context menu items
+ QShortcut *kZoomIn, *kZoomOut, *kNewFile, *kNewDir, *kNewXDG, *kCut, *kCopy, *kPaste, *kRename, \
+ *kFav, *kDel, *kOpSS, *kOpMM, *kOpTerm;
+
+ //Functions for internal use
+ void createShortcuts(); //on init only
+ void createMenus(); //on init only
+
+ BrowserWidget* currentBrowser();
+ QStringList currentDirFiles(); //all the "files" available within the current dir/browser
+
+private slots:
+ //UI BUTTONS/Actions
+
+ // -- Bottom Action Buttons
+ void on_tool_zoom_in_clicked();
+ void on_tool_zoom_out_clicked();
+
+ // -- Top Snapshot Buttons
+ void on_tool_snap_newer_clicked();
+ void on_tool_snap_older_clicked();
+ void on_slider_snap_valueChanged(int val = -1);
+ void direct_snap_selected(QAction*);
+
+ //Top Toolbar buttons
+ void on_actionBack_triggered();
+ void on_actionUp_triggered();
+ void on_actionHome_triggered();
+ void dir_changed(); //user manually changed the directory
+ void on_actionSingleColumn_triggered(bool);
+ void on_actionDualColumn_triggered(bool);
+ void on_actionMenu_triggered();
+
+ // - Other Actions without a specific button on the side
+ void fileCheckSums();
+ void fileProperties();
+ void openTerminal();
+
+
+ //Browser Functions
+ void OpenContextMenu();
+ void UpdateContextMenu();
+ void currentDirectoryChanged(bool widgetonly = false);
+ void dirStatusChanged(QString);
+ void setCurrentBrowser(QString);
+
+ //Context Menu Functions
+ // - DIRECTORY operations
+ void createNewFile();
+ void createNewDir();
+ void createNewXDGEntry();
+ //void createNewSymlink();
+
+ // - Selected FILE operations
+ void cutFiles();
+ void copyFiles();
+ void pasteFiles();
+ void renameFiles();
+ void favoriteFiles();
+ void removeFiles();
+ void runFiles();
+ void runWithFiles();
+ //void attachToNewEmail();
+
+ // - Context-specific operations
+ void openInSlideshow();
+ void openMultimedia();
+
+signals:
+ //Directory loading/finding signals
+ void OpenDirectories(QStringList); //Directories to open in other tabs/columns
+ void findSnaps(QString, QString); //ID, dirpath (Request snapshot information for a directory)
+ void CloseBrowser(QString); //ID (Request that this browser be closed)
+
+ //External App/Widget launching
+ void PlayFiles(LFileInfoList); //open in multimedia player
+ void ViewFiles(LFileInfoList); //open in slideshow
+ void LaunchTerminal(QString); //dirpath
+
+ //System Interactions
+ void CutFiles(QStringList); //file selection
+ void CopyFiles(QStringList); //file selection
+ void PasteFiles(QString, QStringList); //current dir
+ void FavoriteFiles(QStringList); //file selection
+ void RenameFiles(QStringList); //file selection
+ void RemoveFiles(QStringList); //file selection
+ void TabNameChanged(QString, QString); //objID, new tab name
+
+protected:
+ void mouseReleaseEvent(QMouseEvent *);
+
+};
+
+#endif
diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui
new file mode 100644
index 00000000..29660ad4
--- /dev/null
+++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DirWidget</class>
+ <widget class="QWidget" name="DirWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>350</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>350</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0" columnstretch="0,1">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="horizontalSpacing">
+ <number>1</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>2</number>
+ </property>
+ <item row="0" column="0" rowspan="2" colspan="2">
+ <layout class="QHBoxLayout" name="toolbar_layout"/>
+ </item>
+ <item row="2" column="1">
+ <layout class="QVBoxLayout" name="browser_layout_main">
+ <property name="spacing">
+ <number>1</number>
+ </property>
+ <item>
+ <widget class="QFrame" name="group_snaps">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <property name="leftMargin">
+ <number>1</number>
+ </property>
+ <property name="topMargin">
+ <number>1</number>
+ </property>
+ <property name="rightMargin">
+ <number>1</number>
+ </property>
+ <property name="bottomMargin">
+ <number>1</number>
+ </property>
+ <item>
+ <widget class="QToolButton" name="tool_snap">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">padding-right: 5px;</string>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="popupMode">
+ <enum>QToolButton::InstantPopup</enum>
+ </property>
+ <property name="toolButtonStyle">
+ <enum>Qt::ToolButtonTextOnly</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="slider_snap">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="invertedAppearance">
+ <bool>false</bool>
+ </property>
+ <property name="invertedControls">
+ <bool>false</bool>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="tool_snap_older">
+ <property name="text">
+ <string notr="true">...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="tool_snap_newer">
+ <property name="text">
+ <string notr="true">...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="browser_layout"/>
+ </item>
+ </layout>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label_status">
+ <property name="text">
+ <string notr="true">Status</string>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="tool_zoom_in">
+ <property name="toolTip">
+ <string>Increase Icon Sizes</string>
+ </property>
+ <property name="text">
+ <string notr="true">ZoomIn</string>
+ </property>
+ <property name="popupMode">
+ <enum>QToolButton::InstantPopup</enum>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="tool_zoom_out">
+ <property name="toolTip">
+ <string>Decrease Icon Sizes</string>
+ </property>
+ <property name="text">
+ <string notr="true">ZoomOut</string>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ <action name="actionBack">
+ <property name="text">
+ <string notr="true">Back</string>
+ </property>
+ <property name="iconText">
+ <string>Back</string>
+ </property>
+ <property name="toolTip">
+ <string>Go back to previous directory</string>
+ </property>
+ <property name="statusTip">
+ <string>Go back to previous directory</string>
+ </property>
+ </action>
+ <action name="actionUp">
+ <property name="text">
+ <string notr="true">Up</string>
+ </property>
+ <property name="iconText">
+ <string>Up</string>
+ </property>
+ <property name="toolTip">
+ <string>Go to parent directory</string>
+ </property>
+ <property name="statusTip">
+ <string>Go to parent directory</string>
+ </property>
+ </action>
+ <action name="actionHome">
+ <property name="text">
+ <string notr="true">Home</string>
+ </property>
+ <property name="iconText">
+ <string>Home</string>
+ </property>
+ <property name="toolTip">
+ <string>Go to home directory</string>
+ </property>
+ <property name="statusTip">
+ <string>Go to home directory</string>
+ </property>
+ </action>
+ <action name="actionMenu">
+ <property name="text">
+ <string>Menu</string>
+ </property>
+ <property name="toolTip">
+ <string>Select Action</string>
+ </property>
+ </action>
+ <action name="actionSingleColumn">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>SingleColumn</string>
+ </property>
+ <property name="toolTip">
+ <string>Single column view</string>
+ </property>
+ </action>
+ <action name="actionDualColumn">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Dual Column</string>
+ </property>
+ <property name="toolTip">
+ <string>Dual Column View</string>
+ </property>
+ </action>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
bgstack15