1 /*
2 * This file is part of OctoPkg, an open-source GUI for pkgng.
3 * Copyright (C) 2015 Alexandre Albuquerque Arnt
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 *
19 */
20 
21 /*
22  * This is MainWindow's refresh UI components related code
23  */
24 
25 #include "mainwindow.h"
26 #include "searchlineedit.h"
27 #include "ui_mainwindow.h"
28 #include "strconstants.h"
29 #include "uihelper.h"
30 #include "globals.h"
31 #include "src/ui/octopkgtabinfo.h"
32 #include <iostream>
33 #include <cassert>
34 
35 #include <QElapsedTimer>
36 #include <QLabel>
37 #include <QProgressBar>
38 #include <QComboBox>
39 #include <QTextBrowser>
40 #include <QStandardItem>
41 #include <QFutureWatcher>
42 #include <QMutableListIterator>
43 #include <QtConcurrent/QtConcurrentRun>
44 
45 /*
46  * If we have some outdated packages, let's put an angry red face icon in this app!
47  */
refreshAppIcon()48 void MainWindow::refreshAppIcon()
49 {
50   bool enableSystemUpgrade=false;
51 
52   if ((m_outdatedStringList->count() > 0))
53   {
54     setWindowIcon(IconHelper::getIconOctopiRed());
55 
56     if(!isThereAPendingTransaction())
57       enableSystemUpgrade=true;
58   }
59   else
60   {
61     setWindowIcon(IconHelper::getIconOctopiGreen());
62   }
63 
64   ui->actionSystemUpgrade->setEnabled(enableSystemUpgrade);
65 }
66 
67 /*
68  * Inserts the group names into the Groups treeView
69  */
refreshGroupsWidget()70 void MainWindow::refreshGroupsWidget()
71 {
72   /*
73   disconnect(ui->twGroups, SIGNAL(itemSelectionChanged()), this, SLOT(groupItemSelected()));
74 
75   QList<QTreeWidgetItem *> items;
76   ui->twGroups->clear();
77 
78   items.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList("<" + StrConstants::getDisplayAllCategories() + ">")));
79   m_AllGroupsItem = items.at(0);
80   const QStringList*const packageGroups = Package::getPackageGroups();
81   for(QString group: *packageGroups)
82   {
83     items.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(group)));
84   }
85   m_packageRepo.checkAndSetGroups(*packageGroups); // update Package Repository as well
86   delete packageGroups;
87 
88   ui->twGroups->insertTopLevelItems(0, items);
89   ui->twGroups->setCurrentItem(items.at(0));
90   connect(ui->twGroups, SIGNAL(itemSelectionChanged()), this, SLOT(groupItemSelected()));
91   */
92 }
93 
94 /*
95  * User clicked AUR tool button in the toolbar
96  */
remoteSearchClicked()97 void MainWindow::remoteSearchClicked()
98 {
99   if (m_commandExecuting != ectn_NONE && m_commandExecuting != ectn_LOCAL_PKG_REFRESH) return;
100 
101   static bool lastPkgButtonClickedWasRemote = false;
102 
103   if (lastPkgButtonClickedWasRemote && m_actionSwitchToRemoteSearch->isChecked())
104   {
105     disconnect(m_actionGroupSearch, SIGNAL(triggered(QAction*)), this, SLOT(remoteSearchClicked()));
106     m_actionSwitchToRemoteSearch->setChecked(false);
107     //m_actionSwitchToLocalSearch->setChecked(true);
108     connect(m_actionGroupSearch, SIGNAL(triggered(QAction*)), this, SLOT(remoteSearchClicked()));
109   }
110   else/* if (!lastPkgButtonClickedWasRemote && m_actionSwitchToLocalSearch->isChecked())*/
111   {
112     disconnect(m_actionGroupSearch, SIGNAL(triggered(QAction*)), this, SLOT(remoteSearchClicked()));
113     //m_actionSwitchToLocalSearch->setChecked(false);
114     m_actionSwitchToRemoteSearch->setChecked(true);
115     connect(m_actionGroupSearch, SIGNAL(triggered(QAction*)), this, SLOT(remoteSearchClicked()));
116   }
117 
118   //m_leFilterPackage->clear();
119 
120   if (m_actionSwitchToRemoteSearch->isChecked())
121   {
122     m_packageModel->setShowColumnInstalledOn(false);
123     m_leFilterPackage->setPlaceholderText(StrConstants::getLineEditTextRemote());
124     m_leFilterPackage->setToolTip(StrConstants::getRemotePackageSearchTip());
125     ui->menuSearch->setEnabled(false);
126   }
127   else
128   {
129     m_packageModel->setShowColumnInstalledOn(true);
130     m_leFilterPackage->setPlaceholderText(StrConstants::getLineEditTextLocal());
131     m_leFilterPackage->setToolTip("");
132     ui->menuSearch->setEnabled(true);
133   }
134 
135   m_selectedRepository = "";
136 
137   if (m_commandExecuting == ectn_NONE)
138     m_refreshPackageLists = false;
139   else if (m_commandExecuting == ectn_LOCAL_PKG_REFRESH)
140     m_refreshPackageLists = true;
141 
142   metaBuildPackageList();
143   m_cachedPackageInInfo = "";
144   m_cachedPackageInFiles = "";
145   invalidateTabs();
146 
147   if (m_commandExecuting == ectn_LOCAL_PKG_REFRESH)
148   {
149     connect(this, SIGNAL(buildPackageListDone()), this, SLOT(resetTransaction()));
150   }
151 
152   if (m_actionSwitchToRemoteSearch->isChecked())
153   {
154     lastPkgButtonClickedWasRemote = true;
155   }
156   else
157   {
158     lastPkgButtonClickedWasRemote = false;
159   }
160 }
161 
162 /*
163  * Whenever user selects another package group...
164  */
groupItemSelected()165 void MainWindow::groupItemSelected()
166 {
167   //Let us select ALL pkgs from ALL repos!
168   switchToViewAllPackages();
169   m_selectedRepository = "";
170   m_actionRepositoryAll->setChecked(true);
171 
172   if (isAllCategoriesSelected())
173   {
174     m_refreshPackageLists = false;
175   }
176   else
177   {
178     m_refreshPackageLists = true;
179   }
180 
181   m_leFilterPackage->clear();
182   metaBuildPackageList();
183 }
184 
185 /*
186  * Given the package name that owns the file user has just searched, goes to that package in the list
187  */
positionInPkgListSearchByFile()188 void MainWindow::positionInPkgListSearchByFile()
189 {
190   if (m_cic) {
191     delete m_cic;
192     m_cic = NULL;
193   }
194 
195   QString pkgName = g_fwPackageOwnsFile.result();
196 
197   if (!pkgName.isEmpty())
198   {
199     QModelIndex searchColumn = m_packageModel->index(0,
200                                                      PackageModel::ctn_PACKAGE_NAME_COLUMN,
201                                                      QModelIndex());
202     QModelIndexList fi = m_packageModel->match(searchColumn, Qt::DisplayRole, pkgName, -1, Qt::MatchExactly);
203 
204     if (fi.count() >= 1)
205     {
206       ui->tvPackages->setCurrentIndex(fi.at(0));
207       ui->tvPackages->scrollTo(fi.at(0), QAbstractItemView::PositionAtCenter);
208     }
209   }
210   else //The pkg was not found, so we position on the first item of the list!
211   {
212     ui->tvPackages->setCurrentIndex(m_packageModel->index(0,0,QModelIndex()));
213   }
214 }
215 
216 /*
217  * Populates the list of available packages from the given groupName
218  */
buildPackagesFromGroupList(const QString group)219 void MainWindow::buildPackagesFromGroupList(const QString group)
220 {
221   CPUIntensiveComputing cic;
222   const QList<QString>*const list = m_listOfPackagesFromGroup.get();
223   QList<QString>::const_iterator it = list->begin();
224 
225   m_progressWidget->setRange(0, list->count());
226   m_progressWidget->setValue(0);
227   m_progressWidget->show();
228 
229   int installedCount = 0;
230   int counter=0;
231 
232   while(it != list->end())
233   {
234     if (isPackageInstalled(*it)) {
235       ++installedCount;
236     }
237 
238     counter++;
239     m_progressWidget->setValue(counter);
240     ++it;
241   }
242 
243   counter = list->count();
244   m_progressWidget->setValue(counter);
245   m_progressWidget->close();
246 
247   m_packageRepo.checkAndSetMembersOfGroup(group, *list);
248   m_packageModel->applyFilter(m_selectedViewOption, m_selectedRepository, isAllCategories(group) ? "" : group);
249 
250   //Refresh counters
251   m_numberOfInstalledPackages = installedCount;
252   //Refresh statusbar widget
253   refreshStatusBar();
254 
255   reapplyPackageFilter();
256 
257   QModelIndex maux = m_packageModel->index(0, 0, QModelIndex());
258   ui->tvPackages->setCurrentIndex(maux);
259   ui->tvPackages->scrollTo(maux, QAbstractItemView::PositionAtCenter);
260   ui->tvPackages->setCurrentIndex(maux);
261 
262   m_listOfPackagesFromGroup.reset();
263   invalidateTabs();
264   ui->tvPackages->setFocus();
265 
266   refreshToolBar();
267   //refreshStatusBarToolButtons();
268 
269   tvPackagesSelectionChanged(QItemSelection(),QItemSelection());
270 }
271 
272 /*
273  * Executes QFuture to retrieve list of locked packages
274  */
retrieveLockedPackageList()275 void MainWindow::retrieveLockedPackageList()
276 {
277   QEventLoop el;
278   QFuture<QSet<QString> *> f;
279   f = QtConcurrent::run(searchLockedPkgPackages);
280   connect(&g_fwLockedPkg, SIGNAL(finished()), this, SLOT(preBuildLockedPackageList()));
281   connect(&g_fwLockedPkg, SIGNAL(finished()), &el, SLOT(quit()));
282   g_fwLockedPkg.setFuture(f);
283   el.exec();
284 }
285 
286 /*
287  * Executes QFuture to retrive Unrequired Pacman list of packages
288  */
retrieveUnrequiredPackageList()289 void MainWindow::retrieveUnrequiredPackageList()
290 {
291   QEventLoop el;
292   QFuture<QSet<QString> *> f;
293   f = QtConcurrent::run(searchUnrequiredPacmanPackages);
294   connect(&g_fwUnrequiredPacman, SIGNAL(finished()), this, SLOT(preBuildUnrequiredPackageList()));
295   connect(&g_fwUnrequiredPacman, SIGNAL(finished()), &el, SLOT(quit()));
296   g_fwUnrequiredPacman.setFuture(f);
297   el.exec();
298   assert(m_unrequiredPackageList != NULL);
299 }
300 
301 /*
302  * Helper method to assign QFuture for Locked Pkg list of packages
303  */
preBuildLockedPackageList()304 void MainWindow::preBuildLockedPackageList()
305 {
306   m_lockedPackageList = g_fwLockedPkg.result();
307 
308   if(m_debugInfo)
309     std::cout << "Time elapsed obtaining Locked pkgs from 'ALL group' list: " << m_time->elapsed() << " mili seconds." << std::endl << std::endl;
310 }
311 
312 /*
313  * Helper method to assign QFuture for Unrequired Pacman list of packages
314  */
preBuildUnrequiredPackageList()315 void MainWindow::preBuildUnrequiredPackageList()
316 {
317   m_unrequiredPackageList = g_fwUnrequiredPacman.result();
318 
319   if(m_debugInfo)
320     std::cout << "Time elapsed obtaining Unrequired pkgs from 'ALL group' list: " << m_time->elapsed() << " mili seconds." << std::endl << std::endl;
321 }
322 
323 /*
324  * Helper method to deal with the QFutureWatcher result before calling
325  * Pacman package list building method
326  */
preBuildPackageList()327 void MainWindow::preBuildPackageList()
328 {
329   m_listOfPackages.reset(g_fwPkg.result());
330 
331   if(m_debugInfo)
332     std::cout << "Time elapsed obtaining pkgs from 'ALL group' list: " << m_time->elapsed() << " mili seconds." << std::endl;
333 
334   buildPackageList();
335   toggleSystemActions(true);
336 
337   if (!m_initializationCompleted)
338   {
339     //remoteSearchClicked();
340     m_initializationCompleted = true;
341   }
342 }
343 
344 /*
345  * Helper method to deal with the QFutureWatcher result before calling
346  * Pacman packages from group list building method
347  */
preBuildPackagesFromGroupList()348 void MainWindow::preBuildPackagesFromGroupList()
349 {
350   GroupMemberPair result = g_fwPacmanGroup.result();
351   m_listOfPackagesFromGroup.reset(result.second);
352   buildPackagesFromGroupList(result.first);
353 
354   toggleSystemActions(true);
355 
356   emit buildPackagesFromGroupListDone();
357 }
358 
359 /*
360  * Slot to fire the search for all installed packages
361  */
searchForPkgPackages()362 void MainWindow::searchForPkgPackages()
363 {
364   QFuture<QList<PackageListData> *> f;
365   f = QtConcurrent::run(searchPkgPackages);
366   disconnect(&g_fwPkg, SIGNAL(finished()), this, SLOT(preBuildPackageList()));
367   connect(&g_fwPkg, SIGNAL(finished()), this, SLOT(preBuildPackageList()));
368   g_fwPkg.setFuture(f);
369 }
370 
371 /*
372  * Decides which SLOT to call: buildPackageList, buildAURPackageList or buildPackagesFromGroupList
373  */
metaBuildPackageList()374 void MainWindow::metaBuildPackageList()
375 {
376   m_time->start();
377 
378   if (isSearchByFileSelected())
379     m_leFilterPackage->setRefreshValidator(ectn_FILE_VALIDATOR);
380   else if (isRemoteSearchSelected())
381     m_leFilterPackage->setRefreshValidator(ectn_AUR_VALIDATOR);
382   else
383     m_leFilterPackage->setRefreshValidator(ectn_DEFAULT_VALIDATOR);
384 
385   ui->tvPackages->setSelectionMode(QAbstractItemView::ExtendedSelection);
386 
387   //if (ui->twGroups->topLevelItemCount() == 0 || isAllCategoriesSelected())
388   if (m_actionSwitchToRemoteSearch->isChecked())
389   {
390     ui->actionSearchByFile->setEnabled(false);
391     //disconnect(m_leFilterPackage, SIGNAL(textChanged(QString)), this, SLOT(reapplyPackageFilter()));
392     clearStatusBar();
393 
394     m_cic = new CPUIntensiveComputing();
395 
396     if(!m_leFilterPackage->text().isEmpty())
397     {
398       m_toolButtonPacman->hide();
399       disconnect(&g_fwRemoteMeta, SIGNAL(finished()), this, SLOT(preBuildRemotePackageListMeta()));
400 
401       QFuture<QList<PackageListData> *> f;
402       f = QtConcurrent::run(searchRemotePackages, m_leFilterPackage->text());
403       connect(&g_fwRemoteMeta, SIGNAL(finished()), this, SLOT(preBuildRemotePackageListMeta()));
404       g_fwRemoteMeta.setFuture(f);
405     }
406     else
407     {
408       m_listOfRemotePackages = new QList<PackageListData>();
409       buildRemotePackageList();
410       delete m_cic;
411       m_cic = 0;
412       m_leFilterPackage->setFocus();
413     }
414   }
415   else
416   {
417     ui->actionSearchByFile->setEnabled(true);
418     ui->actionSearchByName->setChecked(true);
419 
420     //disconnect(m_leFilterPackage, SIGNAL(textChanged(QString)), this, SLOT(reapplyPackageFilter()));
421     //connect(m_leFilterPackage, SIGNAL(textChanged(QString)), this, SLOT(reapplyPackageFilter()));
422     disconnect(&g_fwPkg, SIGNAL(finished()), this, SLOT(preBuildPackageList()));
423 
424     if (m_refreshPackageLists)
425     {
426       QFuture<QMap<QString, OutdatedPackageInfo> *> f;
427       f = QtConcurrent::run(getOutdatedList);
428       disconnect(&g_fwOutdatedList, SIGNAL(finished()), this, SLOT(searchForPkgPackages()));
429       connect(&g_fwOutdatedList, SIGNAL(finished()), this, SLOT(searchForPkgPackages()));
430       g_fwOutdatedList.setFuture(f);
431     }
432     else
433     {
434       searchForPkgPackages();
435     }
436 
437     if(m_debugInfo)
438       std::cout << m_packageModel->getPackageCount() << " pkgs => " <<
439                  "Time elapsed building pkgs from 'ALL group' list: " << m_time->elapsed() << " mili seconds." << std::endl << std::endl;
440   }
441   /*
442   else //pkg category clicked!
443   {
444     ui->actionSearchByFile->setEnabled(false);
445     toggleSystemActions(false);
446     disconnect(m_leFilterPackage, SIGNAL(textChanged(QString)), this, SLOT(reapplyPackageFilter()));
447     connect(m_leFilterPackage, SIGNAL(textChanged(QString)), this, SLOT(reapplyPackageFilter()));
448     reapplyPackageFilter();
449     disconnect(&g_fwPacmanGroup, SIGNAL(finished()), this, SLOT(preBuildPackagesFromGroupList()));
450 
451     QEventLoop el;
452     QFuture<GroupMemberPair> f;
453     f = QtConcurrent::run(searchPacmanPackagesFromGroup, getSelectedCategory());
454     connect(&g_fwPacmanGroup, SIGNAL(finished()), this, SLOT(preBuildPackagesFromGroupList()));
455     disconnect(this, SIGNAL(buildPackagesFromGroupListDone()), &el, SLOT(quit()));
456     connect(this, SIGNAL(buildPackagesFromGroupListDone()), &el, SLOT(quit()));
457 
458     g_fwPacmanGroup.setFuture(f);
459     el.exec();
460 
461     if(m_debugInfo)
462       std::cout << m_packageModel->getPackageCount() << " pkgs => " <<
463                  "Time elapsed building pkgs from '" << getSelectedCategory().toLatin1().data() << " group' list: " << m_time->elapsed() << " mili seconds." << std::endl << std::endl;
464   }
465   */
466 }
467 
468 /*
469  * Helper method to deal with the QFutureWatcher result before calling
470  * AUR package list building method
471  */
preBuildRemotePackageListMeta()472 void MainWindow::preBuildRemotePackageListMeta()
473 {
474   m_listOfRemotePackages = g_fwRemoteMeta.result();
475 
476   //Let's iterate over those found packages to change their status
477   for (QList<PackageListData>::iterator it = m_listOfRemotePackages->begin();
478        it != m_listOfRemotePackages->end(); ++it)
479   {
480     const PackageRepository::PackageData*const package =
481         m_packageRepo.getFirstPackageByName((*it).name);
482 
483     if (package != NULL)
484     {
485       (*it).status = package->status;
486     }
487   }
488 
489   buildRemotePackageList();
490 
491   if (m_cic) {
492     delete m_cic;
493     m_cic = 0;
494   }
495 
496   //if (m_packageModel->getPackageCount() == 0)
497   {
498     m_leFilterPackage->setFocus();
499   }
500 }
501 
502 /*
503  * Helper method to deal with the QFutureWatcher result before calling
504  * AUR package list building method
505  */
preBuildRemotePackageList()506 void MainWindow::preBuildRemotePackageList()
507 {
508   m_listOfRemotePackages = g_fwRemote.result();
509 
510   if (m_commandExecuting == ectn_NONE)
511   {
512     //Let's iterate over those found packages to change their status
513     for (QList<PackageListData>::iterator it = m_listOfRemotePackages->begin();
514          it != m_listOfRemotePackages->end(); ++it)
515     {
516       const PackageRepository::PackageData*const package =
517           m_packageRepo.getFirstPackageByName((*it).name);
518 
519       if (package != NULL)
520       {
521         (*it).status = package->status;
522       }
523     }
524   }
525 
526   buildRemotePackageList();
527 
528   if (m_cic) {
529     delete m_cic;
530     m_cic = NULL;
531   }
532 
533   m_leFilterPackage->setFocus();
534   emit buildRemotePackageListDone();
535 }
536 
537 /*
538  * Populates the list of found AUR packages (installed [+ non-installed])
539  * given the searchString parameter passed.
540  *
541  */
buildRemotePackageList()542 void MainWindow::buildRemotePackageList()
543 {
544   ui->actionSearchByDescription->setChecked(true);
545   m_leFilterPackage->setRefreshValidator(ectn_AUR_VALIDATOR);
546   m_progressWidget->show();
547 
548   const QSet<QString>*const unrequiredPackageList = Package::getUnrequiredPackageList();
549   QList<PackageListData> *list = m_listOfRemotePackages;
550 
551   m_progressWidget->setRange(0, list->count());
552   m_progressWidget->setValue(0);
553   int counter=0;
554   int installedCount = 0;
555   QList<PackageListData>::const_iterator it = list->begin();
556 
557   while(it != list->end())
558   {
559     if (isPackageInstalled(it->name)) {
560       ++installedCount;
561     }
562     counter++;
563     m_progressWidget->setValue(counter);
564     ++it;
565   }
566 
567   m_packageRepo.setAURData(list, *unrequiredPackageList);
568   m_packageModel->applyFilter(PackageModel::ctn_PACKAGE_DESCRIPTION_FILTER_NO_COLUMN);
569   m_packageModel->applyFilter(ectn_ALL_PKGS, "", "NONE");
570 
571   if (ui->tvPackages->model() != m_packageModel.get())
572   {
573     ui->tvPackages->setModel(m_packageModel.get());
574     initPackageTreeView();
575   }
576 
577   if (list->count() > 0)
578   {
579     QModelIndex maux = m_packageModel->index(0, 0, QModelIndex());
580     ui->tvPackages->setCurrentIndex(maux);
581     ui->tvPackages->scrollTo(maux, QAbstractItemView::PositionAtCenter);
582     ui->tvPackages->setCurrentIndex(maux);
583 
584     refreshTabInfo();
585     refreshTabFiles();
586 
587     if (isPackageTreeViewVisible())
588     {
589       ui->tvPackages->setFocus();
590     }
591   }
592 
593   list->clear();
594 
595   //Refresh counters
596   m_numberOfInstalledPackages = installedCount;
597 
598   if (isRemoteSearchSelected())
599   {
600     m_leFilterPackage->initStyleSheet();
601     QString search = Package::parseSearchString(m_leFilterPackage->text());
602     m_packageModel->applyFilter(search);
603 
604     ui->tvPackages->selectionModel()->clear();
605     QModelIndex mi = m_packageModel->index(0, PackageModel::ctn_PACKAGE_NAME_COLUMN, QModelIndex());
606     ui->tvPackages->setCurrentIndex(mi);
607     ui->tvPackages->scrollTo(mi);
608     invalidateTabs();
609   }
610   else
611   {
612     reapplyPackageFilter();
613   }
614 
615   //Refresh statusbar widget
616   refreshStatusBar();
617 
618   //Refresh application icon
619   refreshAppIcon();
620 
621   counter = list->count();
622   m_progressWidget->setValue(counter);
623   m_progressWidget->close();
624 
625   //ui->tvPackages->setColumnHidden(PackageModel::ctn_PACKAGE_REPOSITORY_COLUMN, true);
626 
627   refreshToolBar();
628   //refreshStatusBarToolButtons();
629 
630   //If we found no packages, let's make another search, this time 'by name'...
631   if (!m_leFilterPackage->text().isEmpty() &&
632       (!m_leFilterPackage->text().contains(QRegularExpression("\\s"))) &&
633       m_packageModel->getPackageCount() == 0 &&
634       ui->actionSearchByDescription->isChecked())
635   {
636     if (m_cic != NULL)
637     {
638       delete m_cic;
639       m_cic = 0;
640     }
641 
642     ui->actionSearchByName->setChecked(true);
643     metaBuildPackageList();
644   }
645 
646   emit buildPackageListDone();
647 }
648 
649 /*
650  * Outputs a list of packages that don't have a description
651  */
showPackagesWithNoDescription()652 void MainWindow::showPackagesWithNoDescription()
653 {
654   bool printHeader = false;
655   QList<PackageListData> *list = Package::getPackageList();
656   QList<PackageListData>::const_iterator it = list->begin();
657 
658   while(it != list->end())
659   {
660     PackageListData pld = *it;
661 
662     if (pld.description == (pld.name + "  "))
663     {
664       if (!printHeader)
665       {
666         std::cout << std::endl << "List of packages without description:" << std::endl << std::endl;
667         printHeader=true;
668       }
669 
670       std::cout << pld.name.toLatin1().data() << std::endl;
671     }
672 
673     ++it;
674   }
675 }
676 
677 /*
678  * Populates the list of available packages (installed [+ non-installed])
679  *
680  * It's called Only: when the selected group is <All> !
681  */
buildPackageList()682 void MainWindow::buildPackageList()
683 {
684   CPUIntensiveComputing cic;
685   /*static QStandardItemModel emptyModel;
686   if (!m_initializationCompleted)
687   {
688     ui->tvPackages->setModel(&emptyModel);
689     removePackageTreeViewConnections();
690   }*/
691 
692   static bool firstTime = true;
693 
694   if(m_refreshPackageLists) //If it's not the starting of the app...
695   {
696     //Let's get outdatedPackages list again!
697     m_outdatedStringList->clear();
698     m_outdatedList = g_fwOutdatedList.result(); //Package::getOutdatedStringList();
699 
700     if(m_debugInfo)
701       std::cout << "Time elapsed retrieving outdated pkgs from 'ALL group' list: " << m_time->elapsed() << " mili seconds." << std::endl;
702 
703     for(QString k: m_outdatedList->keys())
704     {
705       m_outdatedStringList->append(k);
706     }
707 
708     if(m_debugInfo)
709       std::cout << "Time elapsed refreshing outdated pkgs from 'ALL group' list: " << m_time->elapsed() << " mili seconds." << std::endl;
710 
711     m_numberOfOutdatedPackages = m_outdatedStringList->count();
712 
713     delete m_lockedPackageList;
714     m_lockedPackageList = NULL;
715     m_lockedPackageList = Package::getLockedPackageList();
716 
717     delete m_unrequiredPackageList;
718     m_unrequiredPackageList = NULL;
719     m_unrequiredPackageList = Package::getUnrequiredPackageList();
720 
721     if(m_debugInfo)
722       std::cout << "Time elapsed obtaining unrequired pkgs from 'ALL group' list: " << m_time->elapsed() << " mili seconds." << std::endl;
723   }
724 
725   // Fetch package list
726   QList<PackageListData> *list;
727   list = m_listOfPackages.release();
728 
729   //qDebug() << "PASSED...";
730 
731   m_progressWidget->setRange(0, list->count());
732   m_progressWidget->setValue(0);
733   m_progressWidget->show();
734 
735   int counter=0;
736   QList<PackageListData>::const_iterator it = list->begin();
737 
738   while(it != list->end())
739   {
740     counter++;
741     m_progressWidget->setValue(counter);
742     ++it;
743   }
744 
745   if(m_debugInfo)
746     std::cout << "Time elapsed iterating over all pkgs from  'ALL group' list: " << m_time->elapsed() << " mili seconds." << std::endl;
747 
748   counter = list->count();
749   m_progressWidget->setValue(counter);
750   m_progressWidget->close();
751   m_packageRepo.setData(list, *m_unrequiredPackageList);
752 
753   if(m_debugInfo)
754     std::cout << "Time elapsed setting the list to the treeview: " << m_time->elapsed() << " mili seconds." << std::endl;
755 
756   if (ui->actionSearchByDescription->isChecked())
757   {
758     m_packageModel->applyFilter(PackageModel::ctn_PACKAGE_DESCRIPTION_FILTER_NO_COLUMN);
759   }
760   else
761   {
762     m_packageModel->applyFilter(PackageModel::ctn_PACKAGE_NAME_COLUMN);
763   }
764 
765   delete list;
766   list = NULL;
767 
768   if (g_fwLockedPkg.isFinished())
769   {
770     for(QString locked: *m_lockedPackageList)
771     {
772       PackageRepository::PackageData* package = m_packageRepo.getFirstPackageByNameEx(locked);
773       if (package != NULL)
774       {
775         package->status = ectn_LOCKED;
776       }
777     }
778   }
779 
780   if(!firstTime && g_fwOutdatedList.isFinished())
781   {
782     for(QString k: m_outdatedList->keys())
783     {
784       OutdatedPackageInfo opi = m_outdatedList->value(k);
785       PackageRepository::PackageData* package = m_packageRepo.getFirstPackageByNameEx(k);
786       if (package != NULL)
787       {
788         package->status = ectn_OUTDATED;
789         package->outdatedVersion = opi.oldVersion;
790       }
791     }
792   }
793 
794   if (isAllCategoriesSelected()) m_packageModel->applyFilter(m_selectedViewOption, m_selectedRepository, "");
795 
796   reapplyPackageFilter();
797 
798   QModelIndex maux = m_packageModel->index(0, 0, QModelIndex());
799   ui->tvPackages->setCurrentIndex(maux);
800   ui->tvPackages->scrollTo(maux, QAbstractItemView::PositionAtCenter);
801   ui->tvPackages->setCurrentIndex(maux);
802 
803   if (m_initializationCompleted)
804   {
805     invalidateTabs();
806   }
807 
808   if (isPackageTreeViewVisible())
809   {
810     ui->tvPackages->setFocus();
811   }
812 
813   //Refresh statusbar widget
814   refreshStatusBar();
815 
816   //Refresh application icon
817   refreshAppIcon();
818 
819   if (firstTime)
820   {
821     getOutdatedPackageListThreaded();
822 
823     if (isPackageTreeViewVisible())
824     {
825       m_leFilterPackage->setFocus();
826     }
827 
828     //m_initializationCompleted = true;
829     firstTime = false;
830 
831     if (m_callSystemUpgrade)
832     {
833       //First, let us throw away that 'wainting cursor'...
834       QApplication::restoreOverrideCursor();
835       doSystemUpgrade();
836     }
837     else if (m_callSystemUpgradeNoConfirm)
838     {
839       //First, let us throw away that 'wainting cursor'...
840       QApplication::restoreOverrideCursor();
841       doSystemUpgrade(ectn_NOCONFIRM_OPT);
842     }
843     else if (m_packagesToInstallList.count() > 0)
844     {
845       //First, let us throw away that 'wainting cursor'...
846       QApplication::restoreOverrideCursor();
847       doInstallLocalPackages();
848     }
849   }
850 
851   //ui->tvPackages->setColumnWidth(PackageModel::ctn_PACKAGE_SIZE_COLUMN, 10);
852   refreshToolBar();
853   //refreshStatusBarToolButtons();
854   m_refreshPackageLists = true;
855 
856   emit buildPackageListDone();
857   m_leFilterPackage->setFocus();
858 }
859 
860 /*
861  * Whenever horizontal splitter handler is moved
862  */
horizontalSplitterMoved(int pos,int index)863 void MainWindow::horizontalSplitterMoved(int pos, int index)
864 {
865   Q_UNUSED(index)
866 
867   QList<int> l, rl;
868   rl = ui->splitterHorizontal->sizes();
869 
870   if (pos == 0 && rl[0] == 0)
871   {
872     ui->twProperties->tabBar()->hide();
873     //ui->mainToolBar->hide();
874   }
875   else
876   {
877     ui->twProperties->tabBar()->show();
878     //ui->mainToolBar->show();
879   }
880 }
881 
882 /*
883  * Refreshes toolbar in order to insert/remove AUR tool button
884  */
refreshToolBar()885 void MainWindow::refreshToolBar()
886 {
887   /*m_hasAURTool =
888       UnixCommand::hasTheExecutable(StrConstants::getForeignRepositoryToolName()) && !UnixCommand::isRootRunning();
889 
890   if (m_hasAURTool)
891   {
892     if (!ui->mainToolBar->actions().contains(m_actionSwitchToPkgSearch))
893     {
894       ui->mainToolBar->insertAction(m_dummyAction, m_actionSwitchToPkgSearch);
895       m_separatorForActionPkgSearch = ui->mainToolBar->insertSeparator(m_actionSwitchToPkgSearch);
896     }
897   }
898   else
899   {
900     if (ui->mainToolBar->actions().contains(m_actionSwitchToPkgSearch))
901     {
902       bool wasChecked = (m_actionSwitchToPkgSearch->isChecked());
903 
904       ui->mainToolBar->removeAction(m_actionSwitchToPkgSearch);
905       ui->mainToolBar->removeAction(m_separatorForActionPkgSearch);
906 
907       if (wasChecked)
908       {
909         m_actionSwitchToPkgSearch->setChecked(false);
910         ui->twGroups->setEnabled(true);
911         groupItemSelected();
912       }
913     }
914   }*/
915 }
916 
917 /*
918  * Refreshes the toolButtons which indicate outdated packages
919  */
refreshStatusBarToolButtons()920 void MainWindow::refreshStatusBarToolButtons()
921 {
922   if (!isSearchByFileSelected() && !m_actionSwitchToRemoteSearch->isChecked())
923     ui->twGroups->setEnabled(true);
924 }
925 
926 /*
927  * Prints the values of the package counters at the left of the statusBar
928  */
refreshStatusBar()929 void MainWindow::refreshStatusBar()
930 {
931   m_lblSelCounter->setVisible(true);
932   m_lblTotalCounters->setVisible(true);
933   QString text;
934   ui->statusBar->removeWidget(m_toolButtonPacman);
935 
936   int numberOfInstalledPackages = m_packageModel->getInstalledPackagesCount();
937 
938   if(numberOfInstalledPackages > 0)
939   {
940     text = StrConstants::getNumberInstalledPackages(numberOfInstalledPackages);
941   }
942   else if (m_leFilterPackage->text().isEmpty() && !m_packageModel->isFiltered())
943   {
944     text = StrConstants::getNumberInstalledPackages(m_numberOfInstalledPackages);
945   }
946   else
947   {
948     if (isRemoteSearchSelected())
949     {
950       if (m_packageModel->getPackageCount() == 0)
951       {
952         m_lblSelCounter->setText("");
953         m_lblSelCounter->setVisible(false);
954         m_lblTotalCounters->setVisible(false);
955       }
956     }
957 
958     text = StrConstants::getNumberInstalledPackages(0);
959   }
960 
961   m_lblTotalCounters->setText(text);
962   ui->statusBar->addWidget(m_lblTotalCounters);
963 
964   if (g_fwOutdatedList.isFinished() && m_numberOfOutdatedPackages > 0)
965   {
966     m_toolButtonPacman->show();
967 
968     if (m_numberOfOutdatedPackages == 1)
969     {
970       m_toolButtonPacman->setText("(1)");
971       m_toolButtonPacman->setToolTip(StrConstants::getOneNewUpdate());
972     }
973     else
974     {
975       m_toolButtonPacman->setText("(" + QString::number(m_numberOfOutdatedPackages) + ")");
976       m_toolButtonPacman->setToolTip(StrConstants::getNewUpdates(m_numberOfOutdatedPackages));
977     }
978 
979     ui->statusBar->addWidget(m_toolButtonPacman);
980   }
981   else
982   {
983     m_toolButtonPacman->hide();
984     m_toolButtonPacman->setText("");
985     m_toolButtonPacman->setToolTip("");
986   }
987 }
988 
989 /*
990  * Clears the counters at the left of the Statusbar
991  */
clearStatusBar()992 void MainWindow::clearStatusBar()
993 {
994   m_lblSelCounter->clear();
995   m_lblTotalCounters->clear();
996 }
997 
998 /*
999  * Re-populates the HTML view with 'pkgName' package information (tab ONE)
1000  */
refreshTabInfo(QString pkgName)1001 void MainWindow::refreshTabInfo(QString pkgName)
1002 {
1003   const PackageRepository::PackageData*const package = m_packageRepo.getFirstPackageByName(pkgName);
1004   if (package == NULL)
1005     return;
1006 
1007   CPUIntensiveComputing cic;
1008   QTextBrowser *text = ui->twProperties->widget(
1009         ctn_TABINDEX_INFORMATION)->findChild<QTextBrowser*>("textBrowser");
1010 
1011   if (text)
1012   {
1013     text->clear();
1014     text->setHtml(OctopkgTabInfo::formatTabInfo(*package, *m_outdatedList));
1015     text->scrollToAnchor(OctopkgTabInfo::anchorBegin);
1016 
1017     //We have to clear the cached Info contents...
1018     m_cachedPackageInInfo = "";
1019   }
1020 }
1021 
1022 /*
1023  * Re-populates the HTML view with selected package's information (tab ONE)
1024  */
refreshTabInfo(bool clearContents,bool neverQuit)1025 void MainWindow::refreshTabInfo(bool clearContents, bool neverQuit)
1026 {
1027   if(neverQuit == false &&
1028      (ui->twProperties->currentIndex() != ctn_TABINDEX_INFORMATION || !isPropertiesTabWidgetVisible() || !m_initializationCompleted)) return;
1029 
1030   QItemSelectionModel*const selectionModel = ui->tvPackages->selectionModel();
1031   if (clearContents || selectionModel == NULL ||
1032       selectionModel->selectedRows(PackageModel::ctn_PACKAGE_NAME_COLUMN).count() == 0)
1033   {
1034     QTextBrowser *text =
1035         ui->twProperties->widget(ctn_TABINDEX_INFORMATION)->findChild<QTextBrowser*>("textBrowser");
1036 
1037     if (text)
1038     {
1039       text->clear();
1040     }
1041 
1042     m_cachedPackageInInfo = "";
1043     return;
1044   }
1045 
1046   QModelIndex item = selectionModel->selectedRows(PackageModel::ctn_PACKAGE_NAME_COLUMN).first();
1047   const PackageRepository::PackageData*const package = m_packageModel->getData(item);
1048   if (package == NULL) {
1049     assert(false);
1050     return;
1051   }
1052 
1053   //If we are trying to refresh an already displayed package...
1054   if (m_cachedPackageInInfo == package->repository+"#"+package->name+"#"+package->version)
1055   {
1056     if (neverQuit)
1057     {
1058       changeTabWidgetPropertiesIndex(ctn_TABINDEX_INFORMATION);
1059     }
1060 
1061     return;
1062   }
1063 
1064   CPUIntensiveComputing cic;
1065 
1066   /* Appends all info from the selected package! */
1067   QTextBrowser *text = ui->twProperties->widget(
1068         ctn_TABINDEX_INFORMATION)->findChild<QTextBrowser*>("textBrowser");
1069   if (text)
1070   {
1071     text->clear();
1072     text->setHtml(OctopkgTabInfo::formatTabInfo(*package, *m_outdatedList));
1073     text->scrollToAnchor(OctopkgTabInfo::anchorBegin);
1074   }
1075 
1076   m_cachedPackageInInfo = package->repository+"#"+package->name+"#"+package->version;
1077 
1078   if (neverQuit)
1079   {
1080     changeTabWidgetPropertiesIndex(ctn_TABINDEX_INFORMATION);
1081   }
1082 }
1083 
1084 /*
1085  * Re-populates the treeview which contains the file list of selected package (tab TWO)
1086  */
refreshTabFiles(bool clearContents,bool neverQuit)1087 void MainWindow::refreshTabFiles(bool clearContents, bool neverQuit)
1088 {
1089   if (m_progressWidget->isVisible() || !m_initializationCompleted) return;
1090 
1091   if(neverQuit == false &&
1092      (ui->twProperties->currentIndex() != ctn_TABINDEX_FILES || !isPropertiesTabWidgetVisible()))
1093   {
1094     return;
1095   }
1096 
1097   bool filterHasFocus = m_leFilterPackage->hasFocus();
1098   bool tvPackagesHasFocus = ui->tvPackages->hasFocus();
1099 
1100   QItemSelectionModel*const selectionModel = ui->tvPackages->selectionModel();
1101   if (clearContents || selectionModel == NULL ||
1102       selectionModel->selectedRows(PackageModel::ctn_PACKAGE_NAME_COLUMN).count() == 0)
1103   {
1104     QTreeView*const tvPkgFileList =
1105         ui->twProperties->widget(ctn_TABINDEX_FILES)->findChild<QTreeView*>("tvPkgFileList");
1106 
1107     if(tvPkgFileList)
1108     {
1109       QStandardItemModel*const modelPkgFileList = qobject_cast<QStandardItemModel*>(tvPkgFileList->model());
1110       modelPkgFileList->clear();
1111       m_cachedPackageInFiles = "";
1112       closeTabFilesSearchBar();
1113 
1114       if (filterHasFocus) m_leFilterPackage->setFocus();
1115       else if (tvPackagesHasFocus) ui->tvPackages->setFocus();
1116 
1117       return;
1118     }
1119   }
1120 
1121   QModelIndex item = selectionModel->selectedRows(PackageModel::ctn_PACKAGE_NAME_COLUMN).first();
1122   const PackageRepository::PackageData*const package = m_packageModel->getData(item);
1123 
1124   if (package == NULL) {
1125     assert(false);
1126     return;
1127   }
1128 
1129   //If we are trying to refresh an already displayed package...
1130   if (m_cachedPackageInFiles == package->repository+"#"+package->name+"#"+package->version)
1131   {
1132     if (neverQuit)
1133     {
1134       changeTabWidgetPropertiesIndex(ctn_TABINDEX_FILES);
1135       selectFirstItemOfPkgFileList();
1136     }
1137     else
1138     {
1139       QTreeView*const tv = ui->twProperties->currentWidget()->findChild<QTreeView *>("tvPkgFileList") ;
1140       if (tv)
1141         tv->scrollTo(tv->currentIndex());
1142     }
1143 
1144     return;
1145   }
1146 
1147   //Maybe this is a non-installed package...
1148   bool nonInstalled = (package->installed() == false);
1149 
1150   QTreeView*const tvPkgFileList =
1151       ui->twProperties->widget(ctn_TABINDEX_FILES)->findChild<QTreeView*>("tvPkgFileList");
1152 
1153   if (tvPkgFileList)
1154   {
1155     QString pkgName = package->name;
1156     QStringList fileList;
1157     QStandardItemModel *fakeModelPkgFileList = new QStandardItemModel(this);
1158     QStandardItemModel *modelPkgFileList = qobject_cast<QStandardItemModel*>(tvPkgFileList->model());
1159 
1160     modelPkgFileList->clear();
1161     QStandardItem *fakeRoot = fakeModelPkgFileList->invisibleRootItem();
1162     QStandardItem *root = modelPkgFileList->invisibleRootItem();
1163     QStandardItem *lastDir, *item, *lastItem=root, *parent;
1164     bool first=true;
1165     lastDir = root;
1166     QEventLoop el;
1167     QFuture<QStringList> f;
1168     QFutureWatcher<QStringList> fwPackageContents;
1169     f = QtConcurrent::run(Package::getContents, pkgName, !nonInstalled);
1170     connect(&fwPackageContents, SIGNAL(finished()), &el, SLOT(quit()));
1171     fwPackageContents.setFuture(f);
1172 
1173     //Let's wait before we get the pkg file list from the other thread...
1174     el.exec();
1175     fileList = fwPackageContents.result();
1176     QString fullPath;
1177     bool isSymLinkToDir = false;
1178 
1179     int counter = 0;
1180     m_progressWidget->setRange(0, fileList.count());
1181     m_progressWidget->setValue(0);
1182     m_progressWidget->show();
1183 
1184     for ( QString file: fileList )
1185     {
1186       bool isDir = file.endsWith('/');
1187       isSymLinkToDir = false;
1188       QString baseFileName = extractBaseFileName(file);
1189 
1190       //Let's test if it is not a symbolic link to a dir
1191       if(!isDir)
1192       {
1193         QFileInfo fiTestForSymLink(file);
1194         if(fiTestForSymLink.isSymLink())
1195         {
1196           QFileInfo fiTestForDir(fiTestForSymLink.symLinkTarget());
1197           isSymLinkToDir = fiTestForDir.isDir();
1198         }
1199       }
1200 
1201       if(isDir){
1202         if ( first == true ){
1203           item = new QStandardItem ( IconHelper::getIconFolder(), baseFileName );
1204           item->setAccessibleDescription("directory " + item->text());
1205           fakeRoot->appendRow ( item );
1206         }
1207         else{
1208           fullPath = utils::showFullPathOfItem(lastDir->index());
1209           //std::cout << "Testing if " << file.toLatin1().data() << " contains " << fullPath.toLatin1().data() << std::endl;
1210           if ( file.contains ( fullPath )) {
1211             //std::cout << "It contains !!! So " << fullPath.toLatin1().data() << " is its parent." << std::endl;
1212             item = new QStandardItem ( IconHelper::getIconFolder(), baseFileName );
1213             item->setAccessibleDescription("directory " + item->text());
1214             lastDir->appendRow ( item );
1215           }
1216           else{
1217             //std::cout << "It doens't contain..." << std::endl;
1218             parent = lastItem->parent();
1219             if (parent != 0) fullPath = utils::showFullPathOfItem(parent->index());
1220 
1221             do{
1222               //if (parent != 0) std::cout << "Testing if " << file.toLatin1().data() << " contains " << fullPath.toLatin1().data() << std::endl;
1223               if ( parent == 0 || file.contains ( fullPath )) break;
1224               parent = parent->parent();
1225               if (parent != 0) fullPath = utils::showFullPathOfItem(parent->index());
1226             }
1227             while ( parent != fakeRoot );
1228 
1229             item = new QStandardItem ( IconHelper::getIconFolder(), baseFileName );
1230             item->setAccessibleDescription("directory " + item->text());
1231 
1232             if ( parent != 0 )
1233             {
1234               //std::cout << item->text().toLatin1().data() << " is son of " << fullPath.toLatin1().data() << std::endl;
1235               parent->appendRow ( item );
1236             }
1237             else
1238             {
1239               //std::cout << item->text().toLatin1().data() << " is son of <FAKEROOT>" << std::endl;
1240               fakeRoot->appendRow ( item );
1241             }
1242           }
1243         }
1244 
1245         lastDir = item;
1246       }
1247       else if (isSymLinkToDir)
1248       {
1249         item = new QStandardItem ( IconHelper::getIconFolder(), baseFileName );
1250         item->setAccessibleDescription("directory " + item->text());
1251         parent = lastDir;
1252         if (parent != 0) fullPath = utils::showFullPathOfItem(parent->index());
1253 
1254         do{
1255           if ( parent == 0 || file.contains ( fullPath )) break;
1256           parent = parent->parent();
1257           if (parent != 0) fullPath = utils::showFullPathOfItem(parent->index());
1258         }
1259         while ( parent != fakeRoot );
1260 
1261         if (parent != 0)
1262         {
1263           parent->appendRow ( item );
1264         }
1265         else
1266         {
1267           fakeRoot->appendRow ( item );
1268         }
1269       }
1270       else
1271       {
1272         item = new QStandardItem ( IconHelper::getIconBinary(), baseFileName );
1273         item->setAccessibleDescription("file " + item->text());
1274         parent = lastDir;
1275         if (parent != 0) fullPath = utils::showFullPathOfItem(parent->index());
1276 
1277         do{
1278           if ( parent == 0 || file.contains ( fullPath )) break;
1279           parent = parent->parent();
1280           if (parent != 0) fullPath = utils::showFullPathOfItem(parent->index());
1281         }
1282         while ( parent != fakeRoot );
1283 
1284         parent->appendRow ( item );
1285       }
1286 
1287       lastItem = item;
1288       first = false;
1289 
1290       counter++;
1291       m_progressWidget->setValue(counter);
1292       //qApp->processEvents();
1293     }
1294 
1295     m_progressWidget->close();
1296     root = fakeRoot;
1297     fakeModelPkgFileList->sort(0);
1298     modelPkgFileList = fakeModelPkgFileList;
1299     tvPkgFileList->setModel(modelPkgFileList);
1300     tvPkgFileList->header()->setDefaultAlignment( Qt::AlignCenter );
1301     modelPkgFileList->setHorizontalHeaderLabels( QStringList() << StrConstants::getContentsOf().arg(pkgName));
1302   }
1303 
1304   m_cachedPackageInFiles = package->repository+"#"+package->name+"#"+package->version;
1305 
1306   if (neverQuit)
1307   {
1308     changeTabWidgetPropertiesIndex(ctn_TABINDEX_FILES);
1309     selectFirstItemOfPkgFileList();
1310   }
1311 
1312   closeTabFilesSearchBar();
1313 
1314   if (filterHasFocus) m_leFilterPackage->setFocus();
1315   else if (tvPackagesHasFocus) ui->tvPackages->setFocus();
1316 }
1317 
1318 /*
1319  * This SLOT is called every time we press a key at FilterLineEdit
1320  */
reapplyPackageFilter()1321 void MainWindow::reapplyPackageFilter()
1322 {
1323   if (m_actionSwitchToRemoteSearch->isChecked())
1324   {
1325     if (m_leFilterPackage->text() == "")
1326     {
1327         m_packageModel->applyFilter("ççç");
1328         refreshStatusBar();
1329     }
1330     return;
1331   }
1332 
1333   if (!isSearchByFileSelected())
1334   {
1335     bool isFilterPackageSelected = m_leFilterPackage->hasFocus();
1336     QString search = Package::parseSearchString(m_leFilterPackage->text());
1337     m_packageModel->applyFilter(search);
1338 
1339     int numPkgs = m_packageModel->getPackageCount();
1340 
1341     if (m_leFilterPackage->text() != ""){
1342       if (numPkgs > 0) m_leFilterPackage->setFoundStyle();
1343       else m_leFilterPackage->setNotFoundStyle();
1344     }
1345     else{
1346       m_leFilterPackage->initStyleSheet();
1347       m_packageModel->applyFilter("");
1348     }
1349 
1350     if (isFilterPackageSelected || numPkgs == 0)
1351     {
1352       m_leFilterPackage->setFocus();
1353     }
1354 
1355     if (numPkgs == 0)
1356       tvPackagesSelectionChanged(QItemSelection(),QItemSelection());
1357 
1358     ui->tvPackages->selectionModel()->clear();
1359     QModelIndex mi = m_packageModel->index(0, PackageModel::ctn_PACKAGE_NAME_COLUMN, QModelIndex());
1360     ui->tvPackages->setCurrentIndex(mi);
1361     ui->tvPackages->scrollTo(mi);
1362     invalidateTabs();
1363   }
1364   //If we are using "Search By file...
1365   else
1366   {
1367     disconnect(m_leFilterPackage, SIGNAL(textChanged(QString)), this, SLOT(reapplyPackageFilter()));
1368 
1369     m_leFilterPackage->initStyleSheet();
1370 
1371     //We need to provide QCompleter data to the SearchLineEdit...
1372     if (!m_leFilterPackage->text().isEmpty())
1373       m_leFilterPackage->refreshCompleterData();
1374 
1375     connect(m_leFilterPackage, SIGNAL(textChanged(QString)), this, SLOT(reapplyPackageFilter()));
1376   }
1377 }
1378 
1379 /*
1380  * Whenever user selects View/All we show him all the available packages
1381  */
selectedAllPackagesMenu()1382 void MainWindow::selectedAllPackagesMenu()
1383 {
1384   m_selectedViewOption = ectn_ALL_PKGS;
1385   changePackageListModel(ectn_ALL_PKGS, m_selectedRepository);
1386 }
1387 
1388 /*
1389  * Whenever user selects View/Installed we show him only the installed packages
1390  */
selectedInstalledPackagesMenu()1391 void MainWindow::selectedInstalledPackagesMenu()
1392 {
1393   m_selectedViewOption = ectn_INSTALLED_PKGS;
1394   changePackageListModel(ectn_INSTALLED_PKGS, m_selectedRepository);
1395 }
1396 
1397 /*
1398  * Whenever user selects View/Non Installed we show him only the non installed packages
1399  */
selectedNonInstalledPackagesMenu()1400 void MainWindow::selectedNonInstalledPackagesMenu()
1401 {
1402   m_selectedViewOption = ectn_NON_INSTALLED_PKGS;
1403   changePackageListModel(ectn_NON_INSTALLED_PKGS, m_selectedRepository);
1404 }
1405 
1406 /*
1407  * Whenever user selects any of the available repositories in View/Repository submenu,
1408  * we filter the packages from that chosen repo
1409  */
selectedRepositoryMenu(QAction * actionRepoSelected)1410 void MainWindow::selectedRepositoryMenu(QAction *actionRepoSelected)
1411 {
1412   if (actionRepoSelected->text() == StrConstants::getAll())
1413     m_selectedRepository = "";
1414   else
1415     m_selectedRepository = actionRepoSelected->text();
1416 
1417   changePackageListModel(m_selectedViewOption, m_selectedRepository);
1418 }
1419