1 //===========================================
2 // Lumina-DE source code
3 // Copyright (c) 2014-2015, Ken Moore
4 // Available under the 3-clause BSD license
5 // See the LICENSE file for full details
6 //===========================================
7 #include "MainUI.h"
8 #include "ui_MainUI.h"
9
10 #include <QMenu>
11
12 #include "gitCompat.h"
13 #include "gitWizard.h"
14
15 #include <LUtils.h>
16 #include <LDesktopUtils.h>
17 #include <ExternalProcess.h>
18 #include <LFileInfo.h>
19
20 #define DEBUG 0
21 bool rootmode = false;
22
MainUI()23 MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){
24 //for Signal/slot we must register the Typedef of QFileInfoList
25 //qRegisterMetaType<QFileInfoList>("QFileInfoList");
26 qRegisterMetaType< LFileInfoList >("LFileInfoList");
27 //just to silence/fix some Qt connect warnings in QtConcurrent
28 //qRegisterMetaType< QVector<int> >("QVector<int>");
29 //qRegisterMetaType< QList<QPersistentModelIndex> >("QList<QPersistentModelIndex>");
30 waitingToClose = false;
31 //put if statement here to check if running as root
32 rootmode = (getuid()==0);
33
34 ui->setupUi(this);
35 if(DEBUG){ qDebug() << "Initilization:"; }
36 settings = LUtils::openSettings("lumina-desktop", "lumina-fm", this);
37
38 //Reset the UI to the previously used size (if possible)
39 QSize orig = settings->value("preferences/MainWindowSize", QSize()).toSize();
40 if(!orig.isEmpty() && orig.isValid()){
41 //Make sure the old size is larger than the default size hint
42 if(orig.width() < this->sizeHint().width()){ orig.setWidth(this->sizeHint().width()); }
43 if(orig.height() < this->sizeHint().height()){ orig.setHeight(this->sizeHint().height()); }
44 //Also ensure the old size is smaller than the current screen size
45 QSize screen = QApplication::desktop()->availableGeometry(this).size();
46 if(orig.width() > screen.width()){ orig.setWidth(screen.width()); }
47 if(orig.height() > screen.height()){ orig.setHeight(screen.height()); }
48 //Now resize the window
49 this->resize(orig);
50 }
51 //initialize the non-ui widgets
52 if(DEBUG){ qDebug() << " - Tab Bar Setup"; }
53 tabBar = new QTabBar(this);
54 tabBar->setTabsClosable(true);
55 tabBar->setMovable(true); //tabs are independant - so allow the user to sort them
56 tabBar->setShape(QTabBar::RoundedNorth);
57 tabBar->setFocusPolicy(Qt::NoFocus);
58 static_cast<QBoxLayout*>(ui->centralwidget->layout())->insertWidget(0,tabBar);
59 if(DEBUG){ qDebug() << " - Threading"; }
60 workThread = new QThread;
61 workThread->setObjectName("Lumina-fm filesystem worker");
62 worker = new DirData();
63 worker->zfsavailable = LUtils::isValidBinary("zfs");
64 //connect(worker, SIGNAL(DirDataAvailable(QString, QString, LFileInfoList)), this, SLOT(DirDataAvailable(QString, QString, LFileInfoList)) );
65 connect(worker, SIGNAL(SnapshotDataAvailable(QString, QString, QStringList)), this, SLOT(SnapshotDataAvailable(QString, QString, QStringList)) );
66 worker->moveToThread(workThread);
67 if(DEBUG){ qDebug() << " - Context Menu"; }
68 contextMenu = new QMenu(this);
69 radio_view_details = new QRadioButton(tr("Detailed List"), this);
70 radio_view_list = new QRadioButton(tr("Basic List"), this);
71 //radio_view_tabs = new QRadioButton(tr("Prefer Tabs"), this);
72 //radio_view_cols = new QRadioButton(tr("Prefer Columns"), this);
73 ui->menuView_Mode->clear();
74 //ui->menuGroup_Mode->clear();
75 detWA = new QWidgetAction(this);
76 detWA->setDefaultWidget(radio_view_details);
77 listWA = new QWidgetAction(this);
78 listWA->setDefaultWidget(radio_view_list);
79 //tabsWA = new QWidgetAction(this);
80 //tabsWA->setDefaultWidget(radio_view_tabs);
81 //colsWA = new QWidgetAction(this);
82 //colsWA->setDefaultWidget(radio_view_cols);
83 ui->menuView_Mode->addAction(detWA);
84 ui->menuView_Mode->addAction(listWA);
85 //ui->menuGroup_Mode->addAction(tabsWA);
86 //ui->menuGroup_Mode->addAction(colsWA);
87 if(DEBUG){ qDebug() << " - sort Menu"; }
88 menuSort_Mode = new QMenu(this);
89 radio_sort_name = new QRadioButton(tr("Sort by Name"), this);
90 radio_sort_size = new QRadioButton(tr("Sort by Size"), this);
91 radio_sort_type = new QRadioButton(tr("Sort by Type"), this);
92 radio_sort_datemod = new QRadioButton(tr("Sort by Date Modified"), this);
93 radio_sort_datecre = new QRadioButton(tr("Sort by Date Created"), this);
94 ui->menuSort_Mode->clear();
95 sortnameA = new QWidgetAction(this);
96 sortnameA->setDefaultWidget(radio_sort_name);
97 sortsizeA = new QWidgetAction(this);
98 sortsizeA->setDefaultWidget(radio_sort_size);
99 sorttypeA = new QWidgetAction(this);
100 sorttypeA->setDefaultWidget(radio_sort_type);
101 sortdateMA = new QWidgetAction(this);
102 sortdateMA->setDefaultWidget(radio_sort_datemod);
103 sortdateCA = new QWidgetAction(this);
104 sortdateCA->setDefaultWidget(radio_sort_datecre);
105
106
107 ui->menuSort_Mode->addAction(sortnameA);
108 ui->menuSort_Mode->addAction(sortsizeA);
109 ui->menuSort_Mode->addAction(sorttypeA);
110 ui->menuSort_Mode->addAction(sortdateMA);
111 ui->menuSort_Mode->addAction(sortdateCA);
112
113 //Setup the pages
114 //ui->BrowserLayout->clear();
115 ui->page_player->setLayout(new QVBoxLayout());
116 ui->page_image->setLayout(new QVBoxLayout());
117 MW = new MultimediaWidget(this);
118 SW = new SlideshowWidget(this);
119 ui->page_player->layout()->addWidget(MW);
120 ui->page_image->layout()->addWidget(SW);
121
122 //Setup any specialty keyboard shortcuts
123 if(DEBUG){ qDebug() << " - Keyboard Shortcuts"; }
124 nextTabLShort = new QShortcut( QKeySequence(tr("Shift+Left")), this);
125 nextTabRShort = new QShortcut( QKeySequence(tr("Shift+Right")), this);
126 togglehiddenfilesShort = new QShortcut( QKeySequence(tr("Ctrl+H")), this);
127 focusDirWidgetShort = new QShortcut( QKeySequence(tr("Ctrl+L")), this);
128 //toggledirtreepaneShort = new QShortcut( QKeySequence(tr("Ctrl+P")), this);
129
130 //Finish loading the interface
131 workThread->start();
132 if(DEBUG){ qDebug() << " - Icons"; }
133 setupIcons();
134 if(DEBUG){ qDebug() << " - Connections"; }
135 setupConnections();
136 if(DEBUG){ qDebug() << " - Settings"; }
137 loadSettings();
138 if(DEBUG){ qDebug() << " - Bookmarks"; }
139 RebuildBookmarksMenu();
140 if(DEBUG){ qDebug() << " - Devices"; }
141 RebuildDeviceMenu();
142 //Make sure we start on the browser page
143 TRAY = new TrayUI(this);
144 connect(TRAY, SIGNAL(JobsFinished()), this, SLOT(TrayJobsFinished()) );
145 if(DEBUG){ qDebug() << " - Done with init"; }
146 ui->actionOpen_as_Root->setVisible(LUtils::isValidBinary("qsudo"));
147 ui->transferTreeView->setVisible(false);
148 }
149
~MainUI()150 MainUI::~MainUI(){
151 for(int i=0; i<DWLIST.length(); i++){
152 DWLIST[i]->cleanup();
153 }
154 workThread->quit();
155 //Also ensure the work thread is stopped
156 // workThread->wait();
157 }
158
OpenDirs(QStringList dirs)159 void MainUI::OpenDirs(QStringList dirs){
160 //Now open the dirs
161 if(dirs.isEmpty()){ dirs << QDir::homePath(); }
162 QStringList invalid;
163 for(int i=0; i<dirs.length(); i++){
164 if(dirs[i].simplified().isEmpty()){ continue; }
165 //Open this directory in a viewer
166 if(dirs[i].endsWith("/")){ dirs[i].chop(1); }
167 if(!QFile::exists(dirs[i])){ invalid << dirs[i]; continue; }
168 if(DEBUG){ qDebug() << "Open Directory:" << dirs[i]; }
169 ///Get a new Unique ID
170 int id = 0;
171 for(int j=0; j<DWLIST.length(); j++){
172 if(DWLIST[j]->id().section("-",1,1).toInt() >= id){ id = DWLIST[j]->id().section("-",1,1).toInt()+1; }
173 }
174 //Create the new DirWidget
175 DirWidget *DW = new DirWidget("DW-"+QString::number(id), settings, this);
176 DW->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
177 ui->BrowserLayout->addWidget(DW);
178 DWLIST << DW;
179 //Connect the signals/slots for it
180 connect(DW, SIGNAL(OpenDirectories(QStringList)), this, SLOT(OpenDirs(QStringList)) );
181 //connect(DW, SIGNAL(LoadDirectory(QString, QString)), worker, SLOT(GetDirData(QString, QString)) );
182 connect(DW, SIGNAL(findSnaps(QString, QString)), worker, SLOT(GetSnapshotData(QString, QString)) );
183 connect(DW, SIGNAL(PlayFiles(LFileInfoList)), this, SLOT(OpenPlayer(LFileInfoList)) );
184 connect(DW, SIGNAL(ViewFiles(LFileInfoList)), this, SLOT(OpenImages(LFileInfoList)) );
185 connect(DW, SIGNAL(LaunchTerminal(QString)), this, SLOT(OpenTerminal(QString)) );
186 connect(DW, SIGNAL(CutFiles(QStringList)), this, SLOT(CutFiles(QStringList)) );
187 connect(DW, SIGNAL(CopyFiles(QStringList)), this, SLOT(CopyFiles(QStringList)) );
188 connect(DW, SIGNAL(FavoriteFiles(QStringList)), this, SLOT(FavoriteFiles(QStringList)) );
189 connect(DW, SIGNAL(RenameFiles(QStringList)), this, SLOT(RenameFiles(QStringList)) );
190 connect(DW, SIGNAL(RemoveFiles(QStringList)), this, SLOT(RemoveFiles(QStringList)) );
191 connect(DW, SIGNAL(PasteFiles(QString,QStringList)), this, SLOT(PasteFiles(QString, QStringList)) );
192 connect(DW, SIGNAL(CloseBrowser(QString)), this, SLOT(CloseBrowser(QString)) );
193 connect(DW, SIGNAL(TabNameChanged(QString,QString)), this, SLOT(TabNameChanged(QString, QString)) );
194 connect(DW, SIGNAL(treeWidgetSizeChanged(float)), this, SLOT(treeWidgetWidthChanged(float)) );
195 //Now create the tab for this
196 //if(radio_view_tabs->isChecked()){
197 int index = tabBar->addTab( LXDG::findIcon("folder-open",""), dirs[i].section("/",-1) );
198 tabBar->setTabWhatsThis( index, "DW-"+QString::number(id) );
199 tabBar->setCurrentIndex(index);
200 /*}else{
201 //Just make sure the browser tab is visible
202 bool found = false;
203 for(int i=0; i<tabBar->count() && !found; i++){
204 if(tabBar->tabWhatsThis(i)=="browser"){ tabBar->setCurrentIndex(i); found=true; }
205 }
206 if(!found){
207 //Need to create the generic Browser tab
208 int index = tabBar->addTab( LXDG::findIcon("folder-open",""), "Browser" );
209 tabBar->setTabWhatsThis( index, "browser" );
210 tabBar->setCurrentIndex(index);
211 }
212 }*/
213
214 //Initialize the widget with the proper settings
215 if(DEBUG){ qDebug() << "Setup Dir Widget"; }
216 DW->setShowDetails(radio_view_details->isChecked() );
217 DW->setThumbnailSize(settings->value("iconsize", 32).toInt() );
218 DW->showHidden( ui->actionView_Hidden_Files->isChecked() );
219 DW->showThumbnails( ui->actionShow_Thumbnails->isChecked() );
220 //DW->showDirTreePane( ui->actionView_showDirTreePane->isChecked() );
221 DW->adjustTreeWidget( settings->value("dirTree_width", 25.0).toFloat() );
222 DW->setTreeSortMode( settings->value("sortmode","num").toInt() );
223 //Now load the directory
224 if(DEBUG){ qDebug() << "Load Directory"; }
225 DW->ChangeDir(dirs[i]); //kick off loading the directory info
226 }
227 //Update visibilities
228 tabChanged(tabBar->currentIndex());
229 tabBar->setVisible( tabBar->count() > 1 );
230 if(!invalid.isEmpty()){
231 QMessageBox::warning(this, tr("Invalid Directories"), tr("The following directories are invalid and could not be opened:")+"\n"+invalid.join(", ") );
232 }
233 //Double check that there is at least 1 dir loaded
234 //qDebug() << "OpenDirs:" << DWLIST.length() << dirs << invalid << tabBar->currentIndex();
235 if(DWLIST.isEmpty()){ OpenDirs(QStringList()); }
236 waitingToClose = false;
237 ui->menuGit->setEnabled( GIT::isAvailable() );
238 this->showNormal(); //single-instance check - make sure the window is raised again if it was minimized
239 }
240
setupIcons()241 void MainUI::setupIcons(){
242 this->setWindowIcon( LXDG::findIcon("Insight-FileManager","") );
243
244 //Setup all the icons using libLumina
245 // File menu
246 ui->actionNew_Window->setIcon( LXDG::findIcon("window-new","") );
247 ui->actionNew_Tab->setIcon( LXDG::findIcon("tab-new","") );
248 ui->actionSearch->setIcon( LXDG::findIcon("edit-find","") );
249 ui->actionOpen_as_Root->setIcon( LXDG::findIcon("system-file-manager-root","") );
250 ui->actionClose_Browser->setIcon( LXDG::findIcon("tab-close","") );
251 ui->actionClose->setIcon( LXDG::findIcon("application-exit","") );
252
253 // Edit menu
254 ui->actionRename->setIcon( LXDG::findIcon("edit-rename","") );
255 ui->actionCut_Selection->setIcon( LXDG::findIcon("edit-cut","") );
256 ui->actionCopy_Selection->setIcon( LXDG::findIcon("edit-copy","") );
257 ui->actionPaste->setIcon( LXDG::findIcon("edit-paste","") );
258 ui->actionDelete_Selection->setIcon( LXDG::findIcon("edit-delete","") );
259
260 // View menu
261 ui->actionRefresh->setIcon( LXDG::findIcon("view-refresh","") );
262 ui->menuView_Mode->setIcon( LXDG::findIcon("view-choose","") );
263 ui->menuSort_Mode->setIcon(LXDG::findIcon("list-spacing","view-list") );
264
265 // Bookmarks menu
266 ui->actionManage_Bookmarks->setIcon( LXDG::findIcon("bookmarks-organize","") );
267 ui->actionManage_Bookmarks->setShortcut(tr("CTRL+B"));
268 ui->actionAdd_Bookmark->setIcon( LXDG::findIcon("bookmark-new","") );
269
270 //GIT menu
271 ui->actionRepo_Status->setIcon( LXDG::findIcon("git","document-edit-verify") );
272 ui->actionClone_Repository->setIcon( LXDG::findIcon("git","download") );
273
274 // External Devices menu
275 ui->actionScan->setIcon( LXDG::findIcon("system-search","") );
276 ui->actionScan->setShortcut(tr("CTRL+E"));
277 }
278
279 //==========
280 // PRIVATE
281 //==========
setupConnections()282 void MainUI::setupConnections(){
283 connect(tabBar, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)) );
284 connect(tabBar, SIGNAL(tabCloseRequested(int)), this, SLOT(tabClosed(int)) );
285 connect(ui->menuBookmarks, SIGNAL(triggered(QAction*)), this, SLOT(goToBookmark(QAction*)) );
286 connect(ui->menuExternal_Devices, SIGNAL(triggered(QAction*)), this, SLOT(goToDevice(QAction*)) );
287
288 //Radio Buttons
289 connect(radio_view_details, SIGNAL(toggled(bool)), this, SLOT(viewModeChanged(bool)) );
290 connect(radio_view_list, SIGNAL(toggled(bool)), this, SLOT(viewModeChanged(bool)) );
291 //connect(radio_view_tabs, SIGNAL(toggled(bool)), this, SLOT(groupModeChanged(bool)) );
292 //connect(radio_view_cols, SIGNAL(toggled(bool)), this, SLOT(groupModeChanged(bool)) );
293
294 // Sort Buttons
295 connect(radio_sort_name, SIGNAL(toggled(bool)), this, SLOT(sortModeName(bool)) );
296 connect(radio_sort_size, SIGNAL(toggled(bool)), this, SLOT(sortModeSize(bool)) );
297 connect(radio_sort_type, SIGNAL(toggled(bool)), this, SLOT(sortModeType(bool)) );
298 connect(radio_sort_datemod, SIGNAL(toggled(bool)), this, SLOT(sortModeDateM(bool)) );
299 connect(radio_sort_datecre, SIGNAL(toggled(bool)), this, SLOT(sortModeDateC(bool)) );
300
301
302 //Special Keyboard Shortcuts
303 connect(nextTabLShort, SIGNAL(activated()), this, SLOT( prevTab() ) );
304 connect(nextTabRShort, SIGNAL(activated()), this, SLOT( nextTab() ) );
305 connect(togglehiddenfilesShort, SIGNAL(activated()), this, SLOT( togglehiddenfiles() ) );
306 connect(focusDirWidgetShort, SIGNAL(activated()), this, SLOT( focusDirWidget() ) );
307 //connect(toggledirtreepaneShort, SIGNAL(activated()), this, SLOT( toggleDirTreePane() ) );
308
309 }
310
focusDirWidget()311 void MainUI::focusDirWidget()
312 {
313 DirWidget *dir = FindActiveBrowser();
314 if(dir != 0) { dir->setFocusLineDir(); }
315 }
316
togglehiddenfiles()317 void MainUI::togglehiddenfiles()
318 {
319 //change setChecked to inverse value
320 ui->actionView_Hidden_Files->setChecked( !settings->value("showhidden", true).toBool() );
321 // then trigger function
322 on_actionView_Hidden_Files_triggered();
323 }
324
325 /*void MainUI::toggleDirTreePane()
326 {
327 //change setChecked to inverse value
328 ui->actionView_Hidden_Files->setChecked( !settings->value("showdirtree", true).toBool() );
329 // then trigger function
330 on_actionView_showDirTreePane_triggered();
331 }*/
332
loadSettings()333 void MainUI::loadSettings(){
334 //Note: make sure this is run after all the UI elements are created and connected to slots
335 // but before the first directory gets loaded
336 ui->actionView_Hidden_Files->setChecked( settings->value("showhidden", false).toBool() );
337 on_actionView_Hidden_Files_triggered(); //make sure to update the models too
338 ui->actionShow_Thumbnails->setChecked( settings->value("showthumbnails",true).toBool());
339 on_actionShow_Thumbnails_triggered(); //make sure to update models too
340 //ui->actionView_showDirTreePane->setChecked( settings->value("showdirtree", false).toBool());
341 //on_actionView_showDirTreePane_triggered(); //make sure to update the models too
342 ui->actionVerify_File_Delete->setChecked( settings->value("showdeleteprompt", true).toBool());
343 //ui->actionShow_Action_Buttons->setChecked(settings->value("showactions", true).toBool() );
344 //on_actionShow_Action_Buttons_triggered(); //make sure to update the UI
345 //ui->actionShow_Thumbnails->setChecked( settings->value("showthumbnails", true).toBool() );
346 //View Type
347 //qDebug() << "View Mode:" << settings->value("viewmode","details").toString();
348 bool showDetails = (settings->value("viewmode","details").toString()=="details");
349 if(showDetails){ radio_view_details->setChecked(true); }
350 else{ radio_view_list->setChecked(true); }
351 //Grouping type
352 //bool usetabs = (settings->value("groupmode","tabs").toString()=="tabs");
353 //if(usetabs){ radio_view_tabs->setChecked(true); }
354 // else{ radio_view_cols->setChecked(true); }
355 //Sort Mode
356 int sortMode = (settings->value("sortmode","num").toInt() );
357 switch(sortMode){
358 case 0: // Name
359 radio_sort_name->setChecked(true); break;
360 case 1: // Size
361 radio_sort_size->setChecked(true); break;
362 case 2: // Type
363 radio_sort_type->setChecked(true); break;
364 case 3: // Date Modified
365 radio_sort_datemod->setChecked(true); break;
366 case 4: // Date Created
367 radio_sort_datecre->setChecked(true); break;
368
369 } // end sortMode Switch
370 }
371
RebuildBookmarksMenu()372 void MainUI::RebuildBookmarksMenu(){
373 //Create the bookmarks menu
374 QStringList BM = settings->value("bookmarks", QStringList()).toStringList();
375 ui->menuBookmarks->clear();
376 ui->menuBookmarks->addAction(ui->actionManage_Bookmarks);
377 ui->menuBookmarks->addAction(ui->actionAdd_Bookmark);
378 ui->menuBookmarks->addSeparator();
379 bool changed = false;
380 BM.sort(); //Sort alphabetically
381 for(int i=0; i<BM.length(); i++){
382 //NOTE 9/28/16: Don't do existance checks here - if a network drive is specified it can cause the loading process to hang significantly
383 //if(QFile::exists(BM[i].section("::::",1,1)) ){
384 QAction *act = new QAction(BM[i].section("::::",0,0),this);
385 act->setWhatsThis(BM[i].section("::::",1,1));
386 ui->menuBookmarks->addAction(act);
387 /*}else{
388 //Invalid directory - remove the bookmark
389 BM.removeAt(i);
390 i--;
391 changed = true;
392 }*/
393 }
394 if(changed){ settings->setValue("bookmarks",BM); }
395 ui->actionManage_Bookmarks->setEnabled(BM.length()>0);
396 }
397
RebuildDeviceMenu()398 void MainUI::RebuildDeviceMenu(){
399 //Create the External Devices Menu appropriately
400 ui->menuExternal_Devices->clear();
401 ui->menuExternal_Devices->addAction( ui->actionScan );
402 ui->menuExternal_Devices->addSeparator();
403 //Scan for externally mounted devices
404 QStringList devs = LOS::ExternalDevicePaths();
405 //Output Format: <type>::::<filesystem>::::<path> (6/24/14 - version 0.4.0 )
406 // <type> = [USB, HDRIVE, SDCARD, DVD, LVM, UNKNOWN]
407 //qDebug() << "Externally-mounted devices:" << devs;
408 //Now add them to the menu appropriately
409 for(int i=0; i<devs.length(); i++){
410 //Skip hidden mount points (usually only for system usage - not user browsing)
411 QString label, path, fs;
412 //Format inputs as necesary
413 path = devs[i].section("::::",2,2);
414 fs = devs[i].section("::::",1,1);
415 if(path.endsWith("/") && path.length()>1 ){ path.chop(1); }
416 if(path == "/"){ label = tr("Root"); }
417 else{ label = path.section("/",-1).simplified(); }
418 if(label.startsWith(".") ){ continue; } //don't show hidden mountpoint (not usually user-browsable)
419 if(label.endsWith(".desktop")){ label = label.section(".desktop",0,-2); } //chop the shortcut suffix off the end
420 //Create entry for this device
421 if( !fs.simplified().isEmpty()){
422 //Add filesystem type to the label
423 label = QString(tr("%1 (Type: %2)")).arg(label, fs);
424 }
425 QAction *act = new QAction(label,this);
426 act->setWhatsThis(path); //full path to mountpoint
427 act->setToolTip( QString(tr("Filesystem: %1")).arg( devs[i].section("::::",1,1) ) );
428 //Now set the appropriate icon
429 QString type = devs[i].section("::::",0,0);
430 if(type=="USB"){ type = "drive-removable-media-usb"; }
431 else if(type=="HDRIVE" || type=="LVM"){ type = "drive-harddisk"; }
432 else if(type=="SDCARD"){ type = "media-flash-sd-mmc"; }
433 else if(type=="DVD"){ type = "media-optical"; }
434 else{ type = "drive-removable-media"; }
435 act->setIcon( LXDG::findIcon(type, "") );
436 ui->menuExternal_Devices->addAction(act);
437 }
438 }
439
FindActiveBrowser()440 DirWidget* MainUI::FindActiveBrowser(){
441 //Find the current directory
442 DirWidget *curB = 0;
443 //Get the current tab ID to start with
444 QString cur = tabBar->tabWhatsThis(tabBar->currentIndex());
445 //if(cur.startsWith("#")){ cur.clear(); } //multimedia/player tab open
446
447 if(DWLIST.length()==1){
448 //Only 1 browser open - use it
449 curB = DWLIST[0];
450 }else if(cur.startsWith("DW-")){
451 //This is a tab for a browser - just find the matching widget
452 for(int i=0; i<DWLIST.length(); i++){
453 if(DWLIST[i]->id()==cur){ curB = DWLIST[i]; break; }
454 }
455 }else{
456 //This is a bit more complex - either showing multiple columns or a non-browser tab is active
457 if(cur=="browser"){
458 //Column View
459 QWidget *focus = QApplication::focusWidget(); //the widget which currently has focus
460 for(int i=0; i<DWLIST.length(); i++){
461 if(DWLIST[i]->isAncestorOf(focus)){ curB = DWLIST[i]; break; } //This browser has focus
462 }
463 }else{
464 //Non-Browser in focus - use the fallback below
465 }
466 }
467 //if all else fails - just use the first browser in the list (there should always be at least one)
468 if(curB==0 && !DWLIST.isEmpty()){ curB = DWLIST[0]; }
469 return curB;
470 }
471
472 //==============
473 // PRIVATE SLOTS
474 //==============
DisplayStatusBar(QString msg)475 void MainUI::DisplayStatusBar(QString msg){
476 //qDebug() << "message to show in the status bar:" << msg;
477 ui->statusbar->showMessage(msg);
478 }
479
480 //---------------------
481 //Menu Actions
482 //---------------------
on_actionNew_Window_triggered()483 void MainUI::on_actionNew_Window_triggered(){
484 QProcess::startDetached("lumina-fm -new-instance");
485 }
486
on_actionNew_Tab_triggered()487 void MainUI::on_actionNew_Tab_triggered(){
488 OpenDirs(QStringList() << QDir::homePath());
489 }
490
on_actionSearch_triggered()491 void MainUI::on_actionSearch_triggered(){
492 DirWidget *dir = FindActiveBrowser();
493 if(dir==0){ return; }
494 QProcess::startDetached("lumina-search -dir \""+dir->currentDir()+"\"");
495 }
496
on_actionClose_Browser_triggered()497 void MainUI::on_actionClose_Browser_triggered(){
498 tabClosed();
499 }
500
on_actionClose_triggered()501 void MainUI::on_actionClose_triggered(){
502 if(tabBar->count() > 1){
503 if(QMessageBox::Yes != QMessageBox::question(this, tr("Verify Quit"), tr("You have multiple tabs open. Are you sure you want to quit?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes ) ){
504 return;
505 }
506 }
507 qDebug() << "Closing Down...";
508 this->close();
509 }
510
on_actionNew_Dir_triggered()511 void MainUI::on_actionNew_Dir_triggered()
512 {
513 DirWidget::createNewFolder(this, DWLIST.at( tabBar->currentIndex())->currentBrowser() );
514 }
515
on_actionRefresh_triggered()516 void MainUI::on_actionRefresh_triggered(){
517 DirWidget *cur = FindActiveBrowser();
518 if(cur!=0){ cur->refresh(); }
519 }
520
on_actionView_Hidden_Files_triggered()521 void MainUI::on_actionView_Hidden_Files_triggered(){
522 worker->showHidden = ui->actionView_Hidden_Files->isChecked();
523 //Now save this setting for later
524 settings->setValue("showhidden", ui->actionView_Hidden_Files->isChecked());
525 //worker->showHidden = ui->actionView_Hidden_Files->isChecked();
526 //Re-load the current browsers
527 for(int i=0; i<DWLIST.length(); i++){ DWLIST[i]->showHidden( ui->actionView_Hidden_Files->isChecked() ); }//DWLIST[i]->refresh(); }
528
529 }
530
on_actionVerify_File_Delete_triggered()531 void MainUI::on_actionVerify_File_Delete_triggered(){
532 //Now save this setting for later
533 settings->setValue("showdeleteprompt", ui->actionView_Hidden_Files->isChecked());
534 }
535
treeWidgetWidthChanged(float percent)536 void MainUI::treeWidgetWidthChanged(float percent){
537 //NOTE: Percent needs to be between 0-75
538 if(percent > 75){ percent = 75; }
539 settings->setValue("dirTree_width", percent);
540 //Re-load the current browsers
541 for(int i=0; i<DWLIST.length(); i++){ DWLIST[i]->adjustTreeWidget(percent); }
542 }
543
544
on_actionShow_Thumbnails_triggered()545 void MainUI::on_actionShow_Thumbnails_triggered(){
546 //Now save this setting for later
547 bool show = ui->actionShow_Thumbnails->isChecked();
548 settings->setValue("showthumbnails", show);
549 for(int i=0; i<DWLIST.length(); i++){ DWLIST[i]->showThumbnails(show); }
550 }
551
goToBookmark(QAction * act)552 void MainUI::goToBookmark(QAction *act){
553 if(act==ui->actionManage_Bookmarks){
554 BMMDialog dlg(this);
555 dlg.loadSettings(settings);
556 dlg.exec();
557 RebuildBookmarksMenu();
558 }else if(act == ui->actionAdd_Bookmark){
559 CreateBookMark();
560 }else{
561 //Find the current directory
562 DirWidget *dir = FindActiveBrowser();
563 if(dir!=0){
564 dir->ChangeDir(act->whatsThis());
565 return;
566 }
567 //If no current dir could be found - open a new tab/column
568 OpenDirs(QStringList() << act->whatsThis() );
569 }
570 }
571
goToDevice(QAction * act)572 void MainUI::goToDevice(QAction *act){
573 if(act==ui->actionScan){
574 RebuildDeviceMenu();
575 }else{
576 QString action = act->whatsThis();
577 if(action.endsWith(".desktop")){
578 //Find the actual action/directory within this shortcut
579 XDGDesktop xdg(action);
580 if(xdg.type==XDGDesktop::DIR){
581 action = xdg.path; //use the new path
582 }else{
583 //Need to run the full open routine on this shortcut
584 QProcess::startDetached("lumina-open", QStringList() << action);
585 return;
586 }
587 }else if( !QFileInfo(action).isDir() ){
588 //Need to run the full open routine on this file since it is not a directory
589 QProcess::startDetached("lumina-open", QStringList() << action);
590 return;
591 }
592 DirWidget *dir = FindActiveBrowser();
593 if(dir!=0){
594 dir->ChangeDir(action);
595 return;
596 }
597 //If no current dir could be found - open a new tab/column
598 OpenDirs(QStringList() << action );
599 }
600 }
601
viewModeChanged(bool active)602 void MainUI::viewModeChanged(bool active){
603 if(!active){ return; } //on every view change, all radio buttons will call this function - only run this once though
604 bool showDetails = radio_view_details->isChecked();
605 if(showDetails){ settings->setValue("viewmode","details"); }
606 else{ settings->setValue("viewmode","list"); }
607
608 //Re-load the view widgets
609 for(int i=0; i<DWLIST.length(); i++){
610 DWLIST[i]->setShowDetails(showDetails);
611 }
612 ui->menuView_Mode->hide();
613 }
614
615
sortModeName(bool active)616 void MainUI::sortModeName(bool active){
617 if(!active){ return; }
618 bool sortbyName = radio_sort_name->isChecked();
619 settings->setValue("sortmode","0");
620 for(int i=0; i<DWLIST.length(); i++){
621 DWLIST[i]->setTreeSortMode(0);
622 }
623 ui->menuSort_Mode->hide();
624 }
625
sortModeSize(bool active)626 void MainUI::sortModeSize(bool active){
627 if(!active){ return; }
628 bool sortbySize = radio_sort_size->isChecked();
629 settings->setValue("sortmode","1");
630 for(int i=0; i<DWLIST.length(); i++){
631 DWLIST[i]->setTreeSortMode(1);
632 }
633 ui->menuSort_Mode->hide();
634 }
635
sortModeType(bool active)636 void MainUI::sortModeType(bool active){
637 if(!active){ return; }
638 bool sortbyType = radio_sort_type->isChecked();
639 settings->setValue("sortmode","2");
640 for(int i=0; i<DWLIST.length(); i++){
641 DWLIST[i]->setTreeSortMode(2);
642 }
643 ui->menuSort_Mode->hide();
644 }
645
sortModeDateM(bool active)646 void MainUI::sortModeDateM(bool active){
647 if(!active){ return; }
648 bool sortbyDateM = radio_sort_datemod->isChecked();
649 settings->setValue("sortmode","3");
650 for(int i=0; i<DWLIST.length(); i++){
651 DWLIST[i]->setTreeSortMode(3);
652 }
653 ui->menuSort_Mode->hide();
654 }
655
sortModeDateC(bool active)656 void MainUI::sortModeDateC(bool active){
657 if(!active){ return; }
658 bool sortbyDateC = radio_sort_datecre->isChecked();
659 settings->setValue("sortmode","4");
660 for(int i=0; i<DWLIST.length(); i++){
661 DWLIST[i]->setTreeSortMode(4);
662 }
663 ui->menuSort_Mode->hide();
664 }
665
666 /*void MainUI::groupModeChanged(bool active){
667 if(!active){ return; } //on every change, all radio buttons will call this function - only run this once though
668 //bool usetabs = radio_view_tabs->isChecked();
669 //if(usetabs){
670 //settings->setValue("groupmode","tabs");
671 //Now clean up all the tabs (remove the generic one and add the specific ones)
672 for(int i=0; i<tabBar->count(); i++){
673 //Remove all the browser tabs
674 if( !tabBar->tabWhatsThis(i).startsWith("#") ){
675 tabBar->removeTab(i);
676 i--; //go back one to ensure nothing is missed
677 }
678 }
679 //Create all the specific browser tabs for open browsers
680 for(int i=0; i<DWLIST.length(); i++){
681 qDebug() << "Add specific tab:" << DWLIST[i]->currentDir() << DWLIST[i]->id();
682 int tab = tabBar->addTab( LXDG::findIcon("folder-open",""), DWLIST[i]->currentDir().section("/",-1) );
683 tabBar->setTabWhatsThis(tab, DWLIST[i]->id() );
684 //DWLIST[i]->setShowCloseButton(false);
685 }
686 }else{
687 settings->setValue("groupmode","columns");
688 //Now clean up the tabs (remove the specific ones and add a generic one)
689 for(int i=0; i<tabBar->count(); i++){
690 //Remove all the browser tabs
691 if( !tabBar->tabWhatsThis(i).startsWith("#") ){
692 tabBar->removeTab(i);
693 i--; //go back one to ensure nothing is missed
694 }
695 }
696 //Now create the generic "browser" tab
697 int tab = tabBar->addTab( LXDG::findIcon("folder-open",""), tr("Browser") );
698 tabBar->setTabWhatsThis(tab, "browser" );
699 //for(int i=0; i<DWLIST.length(); i++){ DWLIST[i]->setShowCloseButton(true); }
700 }
701 if(tabBar->currentIndex()<0){ tabBar->setCurrentIndex(0); }
702 tabBar->setVisible( tabBar->count() > 1 );
703 QTimer::singleShot(20, this, SLOT(tabChanged()) );
704 }*/
705
on_actionLarger_Icons_triggered()706 void MainUI::on_actionLarger_Icons_triggered(){
707 int size = settings->value("iconsize", 32).toInt();
708 size += 16;
709 for(int i=0; i<DWLIST.length(); i++){ DWLIST[i]->setThumbnailSize(size); }
710 settings->setValue("iconsize", size);
711 }
712
on_actionSmaller_Icons_triggered()713 void MainUI::on_actionSmaller_Icons_triggered(){
714 int size = settings->value("iconsize", 32).toInt();
715 if(size <= 16){ return; }
716 size -= 16;
717 for(int i=0; i<DWLIST.length(); i++){ DWLIST[i]->setThumbnailSize(size); }
718 settings->setValue("iconsize", size);
719 }
720
CreateBookMark()721 void MainUI::CreateBookMark(){
722 QString dir = FindActiveBrowser()->currentDir();
723 bool ok = false;
724 QString name = QInputDialog::getText(this, tr("New Bookmark"), tr("Name:"), QLineEdit::Normal, dir, \
725 &ok, 0, Qt::ImhFormattedNumbersOnly | Qt::ImhUppercaseOnly | Qt::ImhLowercaseOnly);
726 if(!ok || name.isEmpty()){ return; } //cancelled
727 QStringList BM = settings->value("bookmarks",QStringList()).toStringList();
728 if(BM.filter(name+"::::").length() >0){
729 QMessageBox::warning(this, tr("Invalid Name"), tr("This bookmark name already exists. Please choose another.") );
730 QTimer::singleShot(0,this, SLOT(on_actionBookMark_triggered()));
731 return;
732 }
733 BM.append(name+"::::"+dir);
734 BM.sort(); //sort alphabetically by name
735 settings->setValue("bookmarks", BM);
736 //Now rebuild the bookmarks menu
737 RebuildBookmarksMenu();
738 }
739
740 //Git Menu options
on_menuGit_aboutToShow()741 void MainUI::on_menuGit_aboutToShow(){
742 QString dir = FindActiveBrowser()->currentDir();
743 bool inrepo = GIT::isRepo(dir);
744 ui->actionRepo_Status->setEnabled( inrepo );
745 ui->actionClone_Repository->setEnabled( !inrepo );
746 }
747
on_actionRepo_Status_triggered()748 void MainUI::on_actionRepo_Status_triggered(){
749 QString status = GIT::status( FindActiveBrowser()->currentDir() );
750 QMessageBox::information(this, tr("Git Repository Status"), status);
751 }
752
on_actionClone_Repository_triggered()753 void MainUI::on_actionClone_Repository_triggered(){
754 GitWizard *dlg = new GitWizard(this);
755 dlg->setWorkingDir( FindActiveBrowser()->currentDir() );
756 dlg->show();
757 }
758
759
tabChanged(int tab)760 void MainUI::tabChanged(int tab){
761 if(tab<0){ tab = tabBar->currentIndex(); }
762 if(tab < 0){ return; }
763 //Load the directory contained in the new tab
764 QString info = tabBar->tabWhatsThis(tab); //get the full directory
765 if(info.isEmpty()){ return; } //unknown tab (this happens while we are in the middle of making changes to tabs - just ignore it)
766 //qDebug() << "Change to Tab:" << tab << tabBar->tabText(tab);
767 //qDebug() << " -- ID:" << info;
768 if(info=="#MW"){ ui->stackedWidget->setCurrentWidget(ui->page_player); }
769 else if(info=="#SW"){ ui->stackedWidget->setCurrentWidget(ui->page_image); }
770 else{
771 ui->stackedWidget->setCurrentWidget(ui->page_browser);
772 //if(radio_view_tabs->isChecked()){
773 for(int i=0; i<DWLIST.length(); i++){
774 DWLIST[i]->setVisible(DWLIST[i]->id()==info);
775 }
776 /*}else{
777 //For columns, all widgets need to be visible
778 for(int i=0; i<DWLIST.length(); i++){
779 DWLIST[i]->setVisible(true);
780 }
781 }*/
782 }
783 tabBar->setVisible( tabBar->count() > 1 );
784 }
785
tabClosed(int tab)786 void MainUI::tabClosed(int tab){
787 if(tabBar->count()==1){ return; } //Can't close the only tab
788 if(tab < 0){ tab = tabBar->currentIndex(); }
789 QString info = tabBar->tabWhatsThis(tab);
790 if(info=="browser"){ return; }
791 //qDebug() << "Tab Closed:" << info;
792 if(!info.startsWith("#")){
793 for(int i=0; i<DWLIST.length(); i++){
794 if(info == DWLIST[i]->id()){
795 DWLIST[i]->cleanup();
796 delete DWLIST.takeAt(i);
797 break;
798 }
799 }
800 }else if(info=="#MW"){
801 MW->Cleanup(); //prepare it to be hidden/removed
802 }
803 //Remove the tab (will automatically move to a different one);
804 qDebug() << "Closing tab:" << tab << tabBar->tabText(tab);
805 tabBar->removeTab(tab);
806 tabBar->setVisible( tabBar->count() > 1 );
807 if(DWLIST.isEmpty()){ OpenDirs(QStringList() << QDir::homePath() ); }
808 }
809
prevTab()810 void MainUI::prevTab(){
811 int cur = tabBar->currentIndex();
812 if(cur == 0){ tabBar->setCurrentIndex( tabBar->count()-1 ); }
813 else{ tabBar->setCurrentIndex( cur-1 ); }
814 }
815
nextTab()816 void MainUI::nextTab(){
817 int cur = tabBar->currentIndex();
818 if(cur == (tabBar->count()-1) ){ tabBar->setCurrentIndex(0); }
819 else{ tabBar->setCurrentIndex( cur+1 ); }
820 }
821
822
SnapshotDataAvailable(QString id,QString dir,QStringList list)823 void MainUI::SnapshotDataAvailable(QString id , QString dir, QStringList list){
824 for(int i=0; i<DWLIST.length(); i++){
825 if(id == DWLIST[i]->id()){
826 DWLIST[i]->LoadSnaps(dir, list);
827 break;
828 }
829 }
830 }
831
OpenPlayer(LFileInfoList list)832 void MainUI::OpenPlayer(LFileInfoList list){
833 //See if the tab is available for the multimedia player
834 int tab = -1;
835 for(int i=0; i<tabBar->count(); i++){
836 if(tabBar->tabWhatsThis(i)=="#MW"){ tab=i; break;}
837 }
838 if(tab<0){
839 //Need to create a new tab
840 tab = tabBar->addTab(LXDG::findIcon("media-playback-start",""), tr("Multimedia"));
841 tabBar->setTabWhatsThis(tab,"#MW");
842 //Also clear the info in the player
843 MW->ClearPlaylist();
844 }
845 //Load the data into the player
846 MW->LoadMultimedia(list);
847 //Switch to the player tab
848 tabBar->setCurrentIndex(tab);
849 }
850
OpenImages(LFileInfoList list)851 void MainUI::OpenImages(LFileInfoList list){
852 int tab = -1;
853 for(int i=0; i<tabBar->count(); i++){
854 if(tabBar->tabWhatsThis(i)=="#SW"){ tab=i; break;}
855 }
856 if(tab<0){
857 //Need to create a new tab
858 tab = tabBar->addTab(LXDG::findIcon("media-slideshow",""), tr("Slideshow"));
859 tabBar->setTabWhatsThis(tab,"#SW");
860 //Also clear the info in the viewer
861 SW->ClearImages();
862 }
863 //Load the data into the viewer
864 SW->LoadImages(list);
865 //Switch to the player tab
866 tabBar->setCurrentIndex(tab);
867 QTimer::singleShot(20, SW, SLOT(refresh()) );
868 }
869
OpenTerminal(QString dirpath)870 void MainUI::OpenTerminal(QString dirpath){
871 //we use the application defined as the default terminal
872 //QSettings sessionsettings( QSettings::UserScope, "LuminaDE","sessionsettings", this);
873 //xterm remains the default
874 QString defTerminal = LXDG::findDefaultAppForMime("application/terminal"); //sessionsettings.value("default-terminal", "xterm").toString();
875 qDebug() << "Found default terminal:" << defTerminal;
876 //Now get the exec string and run it
877 QString cmd = LUtils::GenerateOpenTerminalExec(defTerminal, dirpath);
878 //qDebug() << "Starting Terminal with command:" << cmd;
879 QProcess::startDetached(cmd);
880
881 }
882
CutFiles(QStringList list)883 void MainUI::CutFiles(QStringList list){
884 qDebug() << "Cut Files:" << list;
885 if(list.isEmpty()){ return; } //nothing selected
886 //Format the data string
887 QList<QUrl> urilist; //Also assemble a URI list for cros-app compat (no copy/cut distinguishing)
888 for(int i=0; i<list.length(); i++){
889 urilist << QUrl::fromLocalFile(list[i]);
890 list[i] = list[i].prepend("cut::::");
891 }
892 //Now save that data to the global clipboard
893 QMimeData *dat = new QMimeData;
894 dat->clear();
895 dat->setData("x-special/lumina-copied-files", list.join("\n").toLocal8Bit());
896 dat->setUrls(urilist); //the text/uri-list mimetype - built in Qt conversion/use
897 QApplication::clipboard()->clear();
898 QApplication::clipboard()->setMimeData(dat);
899 //Update all the buttons to account for clipboard change
900 //for(int i=0; i<DWLIST.length(); i++){ DWLIST[i]->refreshButtons(); }
901 }
902
CopyFiles(QStringList list)903 void MainUI::CopyFiles(QStringList list){
904 qDebug() << "Copy Files:" << list;
905 if(list.isEmpty()){ return; } //nothing selected
906 //Format the data string
907 QList<QUrl> urilist; //Also assemble a URI list for cros-app compat (no copy/cut distinguishing)
908 for(int i=0; i<list.length(); i++){
909 urilist << QUrl::fromLocalFile(list[i]);
910 list[i] = list[i].prepend("copy::::");
911 }
912 //Now save that data to the global clipboard
913 QMimeData *dat = new QMimeData;
914 dat->clear();
915 dat->setData("x-special/lumina-copied-files", list.join("\n").toLocal8Bit());
916 dat->setUrls(urilist); //the text/uri-list mimetype - built in Qt conversion/use
917 QApplication::clipboard()->clear();
918 QApplication::clipboard()->setMimeData(dat);
919 //Update all the buttons to account for clipboard change
920 //for(int i=0; i<DWLIST.length(); i++){ DWLIST[i]->refreshButtons(); }
921 }
922
PasteFiles(QString dir,QStringList raw)923 void MainUI::PasteFiles(QString dir, QStringList raw){
924 qDebug() << "Paste Files:" << dir;
925 QStringList cut, copy, newcut, newcopy;
926 if(raw.isEmpty()){
927 //Pull info from the clipboard
928 const QMimeData *dat = QApplication::clipboard()->mimeData();
929 raw = QString(dat->data("x-special/lumina-copied-files")).split("\n");
930 }
931 if(!dir.endsWith("/")){ dir.append("/"); }
932 for(int i=0; i<raw.length(); i++){
933 if(raw[i].startsWith("cut::::")){
934 cut << raw[i].section("::::",1,50);
935 newcut << dir+raw[i].section("::::",1,50).section("/",-1);
936 }
937 else if(raw[i].startsWith("copy::::")){
938 copy << raw[i].section("::::",1,50);
939 newcopy<< dir+raw[i].section("::::",1,50).section("/",-1);
940 }
941 }
942 //bool errs = false;
943 //Perform the copy/move operations
944 //worker->pauseData = true; //pause any info requests
945 if(!copy.isEmpty()){
946 qDebug() << "Paste Copy:" << copy << "->" << newcopy;
947 TRAY->StartOperation( TrayUI::COPY, copy, newcopy);
948 /*FODialog dlg(this);
949 if( !dlg.CopyFiles(copy, newcopy) ){ return; } //cancelled
950 dlg.show();
951 dlg.exec();
952 errs = errs || !dlg.noerrors;*/
953 }
954 if(!cut.isEmpty()){
955 qDebug() << "Paste Cut:" << cut << "->" << newcut;
956 TRAY->StartOperation(TrayUI::MOVE, cut, newcut);
957 /*FODialog dlg(this);
958 if(!dlg.MoveFiles(cut, newcut) ){ return; } //cancelled
959 dlg.show();
960 dlg.exec();
961 errs = errs || !dlg.noerrors;*/
962 }
963 //worker->pauseData = false; //resume info requests
964 //Modify the clipboard appropriately
965 if(!cut.isEmpty()){
966 //Now clear the clipboard since those old file locations are now invalid
967 QApplication::clipboard()->clear();
968 if(!copy.isEmpty()){
969 //There were also files copied: save those files back into the clipboard
970 QMimeData *dat = new QMimeData;
971 dat->clear();
972 dat->setData("x-special/lumina-copied-files", raw.filter("copy::::").join("\n").toLocal8Bit());
973 QApplication::clipboard()->setMimeData(dat);
974 }
975 }
976 //Update all the buttons to account for clipboard change
977 //for(int i=0; i<DWLIST.length(); i++){ DWLIST[i]->refresh(); }
978 }
979
FavoriteFiles(QStringList list)980 void MainUI::FavoriteFiles(QStringList list){
981 qDebug() << "Favorite Files:" << list;
982 for(int i=0; i<list.length(); i++){
983 LDesktopUtils::addFavorite(list[i]);
984 }
985 //Might want to make this a "toggle" instead of an add later on...
986 }
987
RenameFiles(QStringList list)988 void MainUI::RenameFiles(QStringList list){
989 qDebug() << "Rename Files:" << list;
990 for(int i=0; i<list.length(); i++){
991 QString fname = list[i];
992 QString path = fname;
993 fname = fname.section("/",-1); //turn this into just the file name
994 path.chop(fname.length()); //turn this into the base directory path (has a "/" at the end)
995 //Now prompt for the new filename
996 bool ok = false;
997 QString nname = QInputDialog::getText(this, tr("Rename File"),tr("New Name:"), QLineEdit::Normal, fname, &ok);
998 if(!ok || nname.isEmpty()){ return; } //cancelled
999 //Now check for a file extension and add it if necessary
1000 QString oext = fname.section(".",-1);
1001 if("."+oext == fname){ oext.clear(); } //hidden file without an extension
1002 else if(oext==fname){ oext.clear(); } //no extension
1003 QString next = nname.section(".",-1);
1004 if(next==nname){ next.clear(); } //no extension
1005 if(next.isEmpty() && !oext.isEmpty()){
1006 nname.append( "."+oext );
1007 }
1008 //Check if this filename already exists
1009 bool overwrite = QFile::exists(path+nname);
1010 if(overwrite){
1011 if(QMessageBox::Yes != QMessageBox::question(this, tr("Overwrite File?"), tr("An existing file with the same name will be replaced. Are you sure you want to proceed?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){
1012 return; //cancelled
1013 }
1014 }
1015 //Now perform the move
1016 //Don't pause the background worker for a simple rename - this operation is extremely fast
1017 qDebug() << "Rename:" << path+fname << "->" << path+nname;
1018 TRAY->StartOperation(TrayUI::MOVE, QStringList() << path+fname, QStringList() << path+nname);
1019 /*FODialog dlg(this);
1020 dlg.setOverwrite(overwrite);
1021 dlg.MoveFiles(QStringList() << path+fname, QStringList() << path+nname);
1022 dlg.show();
1023 dlg.exec();*/
1024 } //end loop over list of files
1025 }
1026
RemoveFiles(QStringList list)1027 void MainUI::RemoveFiles(QStringList list){
1028 if(list.isEmpty()){ return; } //nothing selected
1029 qDebug() << "Remove Files:" << list;
1030 QStringList paths, names;
1031 for(int i=0; i<list.length(); i++){
1032 paths << list[i];
1033 names << list[i].section("/",-1);
1034 }
1035
1036 //Verify permanent removal of file/dir
1037 if(ui->actionVerify_File_Delete->isChecked()){
1038 QMessageBox dlgQ(QMessageBox::Question, tr("Verify Removal"), tr("WARNING: This will permanently delete the file(s) from the system!")+"\n"+tr("Are you sure you want to continue?"), QMessageBox::Yes | QMessageBox::No, this);
1039 dlgQ.setDetailedText(tr("Items to be removed:")+"\n\n"+names.join("\n"));
1040 dlgQ.exec();
1041 if(dlgQ.result() != QMessageBox::Yes){ return; } //cancelled
1042 }
1043
1044 //Now remove the file/dir
1045 qDebug() << " - Delete: "<<paths;
1046 TRAY->StartOperation(TrayUI::DELETE, paths, QStringList());
1047 //worker->pauseData = true; //pause any info requests
1048 /*FODialog dlg(this);
1049 dlg.RemoveFiles(paths);
1050 dlg.show();
1051 dlg.exec();*/
1052 //worker->pauseData = false; //resume info requests
1053 //for(int i=0; i<DWLIST.length(); i++){ DWLIST[i]->refresh(); }
1054 }
1055
CloseBrowser(QString ID)1056 void MainUI::CloseBrowser(QString ID){
1057 //Find the tab associated with this browser first
1058 for(int i=0; i<tabBar->count(); i++){
1059 if(tabBar->tabWhatsThis(i)==ID){
1060 tabBar->removeTab(i);
1061 break;
1062 }
1063 }
1064 //Now remove the browser itself
1065 for(int i=0; i<DWLIST.length(); i++){
1066 if(DWLIST[i]->id()==ID){
1067 delete DWLIST.takeAt(i);
1068 break;
1069 }
1070 }
1071 //If the last browser was just closed, create a new one
1072 if(DWLIST.isEmpty()){
1073 OpenDirs(QStringList() << QDir::homePath());
1074 }
1075 }
1076
TabNameChanged(QString id,QString name)1077 void MainUI::TabNameChanged(QString id, QString name){
1078 for(int i=0; i<tabBar->count(); i++){
1079 if(tabBar->tabWhatsThis(i)==id){
1080 tabBar->setTabText(i, name);
1081 return;
1082 }
1083 }
1084 }
1085
TrayJobsFinished()1086 void MainUI::TrayJobsFinished(){
1087 if(waitingToClose){ this->close(); }
1088 }
1089
1090 //=============
1091 // PROTECTED
1092 //=============
closeEvent(QCloseEvent * ev)1093 void MainUI::closeEvent(QCloseEvent *ev){
1094 //See if the tray is active or not first
1095 if(TRAY!=0){
1096 if(TRAY->isVisible() && !waitingToClose){
1097 this->hide();
1098 ev->ignore();
1099 waitingToClose = true;
1100 return;
1101 }
1102 }
1103 QMainWindow::closeEvent(ev); //continue normal close routine
1104 }
1105
on_actionOpen_as_Root_triggered()1106 void MainUI::on_actionOpen_as_Root_triggered()
1107 {
1108 ExternalProcess::launch("qsudo lumina-fm");
1109 }
1110