source: src-qt4/pc-mounttray/menuItem.cpp @ 1f0939e

9.1-release9.2-releasereleng/10.0releng/10.0.1
Last change on this file since 1f0939e was 1f0939e, checked in by Kris Moore <kris@…>, 12 months ago
  • Initial merge of code from PC-BSD SVN repo for my private (pre-release) hacking
  • Property mode set to 100644
File size: 12.3 KB
Line 
1#include <pcbsd-utils.h>
2#include "menuItem.h"
3
4
5MenuItem::MenuItem(QWidget* parent, QString newdevice, QString newlabel, QString newtype, QString newfs) : QWidgetAction(parent)
6{
7  AMFILE= QDir::homePath() + "/.pc-automounttray";   //File to save/load all the devices to be automounted
8  //Set the device info variables
9  if( !newdevice.startsWith(DEVICEDIR) ){ newdevice.prepend(DEVICEDIR); }
10  device = newdevice;
11  devType = newtype;
12  filesystem = newfs;
13  //Create the layout
14  QGridLayout* layout = new QGridLayout();
15  QHBoxLayout* hlayout = new QHBoxLayout();
16  //Create the gui items
17  devLabel = new QLabel;
18    devLabel->setToolTip(device);
19    devLabel->setText(newlabel);
20   
21  devIcon = new QLabel;
22    devIcon->setToolTip(device);
23  currentSpace = new QProgressBar;
24    currentSpace->setMinimum(0);
25  pushMount = new QPushButton;
26  checkAutomount = new QCheckBox;
27    checkAutomount->setChecked( checkSavedAutoMount() );
28    checkAutomount->setText( tr("Auto-mount this device") );
29  //Add the widgets to the layout
30  layout->addWidget(devIcon,0,0,3,1);   
31  hlayout->addWidget(devLabel);
32  hlayout->addWidget(pushMount);
33  layout->addLayout(hlayout,0,1);
34  layout->addWidget(currentSpace,1,1);
35  layout->addWidget(checkAutomount,2,1);
36  //Set the layout
37  frame = new QWidget();
38  frame->setLayout(layout);
39  this->setDefaultWidget(frame);
40
41  //Connect the signals/slots
42  connect(pushMount,SIGNAL(clicked()), this, SLOT(slotMountClicked()));
43  connect(checkAutomount,SIGNAL(toggled(bool)),this,SLOT(slotAutoMountToggled(bool)));
44
45  //Setup the device Icon based on the type
46  if(devType == "USB"){ devIcon->setPixmap(QPixmap(":icons/usb.png")); }
47  else if(devType == "SATA"){ devIcon->setPixmap(QPixmap(":icons/harddrive.png")); }
48  else if(devType == "SD"){ devIcon->setPixmap(QPixmap(":icons/sdcard.png")); }
49  if(devType == "CD9660"){ devIcon->setPixmap(QPixmap(":icons/dvd.png")); }
50  //Start the automount procedure if necessary
51  if(checkAutomount->isChecked()){
52    QTimer::singleShot(500,this,SLOT( slotMountClicked() ));
53  }
54  //Update the Item based upon current device status
55  updateItem();
56
57}
58
59MenuItem::~MenuItem(){
60}
61
62/*
63  PUBLIC FUNCTIONS
64*/
65
66void MenuItem::updateItem(){
67  //Update the item visuals, based upon current device status
68  if( isConnected() ){
69    if( isMounted() ){
70      if(mountpoint.isEmpty()){
71        //detect the current mountpoint
72        QString output = Utils::runShellCommandSearch("mount",device);
73        mountpoint = output.section(" on ",1,1).section(" (",0,0).replace(" ","-");
74      }
75      devIcon->setEnabled(TRUE);  //Make the icon full color
76      devIcon->setToolTip(device+"\n"+QString(tr("Mounted at %1")).arg(mountpoint));
77      pushMount->setText(tr("Eject"));
78      pushMount->setIcon(QIcon(":icons/eject.png"));
79      checkAutomount->setVisible(TRUE);
80    }else{       
81      devIcon->setEnabled(FALSE); //Grey out the icon if not mounted
82      devIcon->setToolTip(device);
83      pushMount->setText(tr("Mount"));
84      pushMount->setIcon(QIcon(":icons/mount.png"));
85      checkAutomount->setVisible(FALSE);
86    }
87  }else{
88    emit itemRemoved(device);
89    return;
90  }
91  //Set visibility and sizes on progressbar
92  updateSizes();
93}
94       
95//Getters
96QString MenuItem::getDeviceName(){
97  return devLabel->text();     
98}
99       
100//Device information
101bool MenuItem::isConnected(){
102  if( QFile::exists(device) ){ return TRUE; }
103  else{ return FALSE; }
104}
105
106bool MenuItem::isMounted(){
107  //Check if device is mounted
108  QString chk = Utils::runShellCommandSearch("mount",device); 
109  if(chk.isEmpty() ){ chk = Utils::runShellCommandSearch("mount",devLabel->text().replace(" ","-")); } 
110
111  if(chk.isEmpty() ){ return FALSE; }
112  else{ return TRUE; }
113}
114
115//Cleanup function
116void MenuItem::cleanup(){
117  if( isMounted() ){
118    unmountItem(); //unmount and remove mountpoint
119  }else{
120    //Just check for mountpoint removal
121    if(QFile::exists(mountpoint)){
122      qDebug() << "Removing old mountpoint:" << mountpoint;
123      QString output = Utils::runShellCommand("rmdir "+mountpoint).join(" ");
124      if(!output.isEmpty()){ qDebug() << " -Error:" <<output; }
125    }
126  }
127}
128/*
129  PRIVATE FUNCTIONS
130*/
131void MenuItem::slotMountClicked(){
132  if( isConnected() ){
133    if( !isMounted() ){
134      mountItem();
135    }else{
136      unmountItem(); 
137    }
138  }else{
139    emit itemRemoved(device);     
140  }
141  updateItem();
142}
143
144void MenuItem::slotAutoMountToggled(bool checked){
145  qDebug() << "Auto-mount toggled for:" << device << checked;
146  QString entry = devLabel->text()+":::"+devType+":::"+filesystem;
147  if(checked){
148    //Add this entry to the auto-mount file
149    QString cmd = "echo \""+entry+"\" >> "+AMFILE;
150    system( cmd.toUtf8() );
151  }else{
152    //Remove this entry from the automount file
153    QString tmpFile = AMFILE+".tmp";
154    QString cmd = "cat "+AMFILE+" | grep -v "+entry+" > "+tmpFile+"; mv "+tmpFile+" "+AMFILE;
155    system( cmd.toUtf8() );
156  }
157}
158
159bool MenuItem::checkSavedAutoMount(){
160  if(QFile::exists(AMFILE)){
161    QString cmd = "cat "+AMFILE;
162    QString search = devLabel->text() +" "+ devType +" "+ filesystem;
163    QString chk = Utils::runShellCommandSearch(cmd, search);
164    if( chk.isEmpty() ){ return FALSE; }
165    else{ return TRUE; }
166  }else{
167    return FALSE;
168  }
169}
170
171void MenuItem::mountItem(){
172  //Mount the device
173 
174  //Create the full path to the mountpoint
175  QString deviceName = devLabel->text();
176  QString mntpoint = MOUNTDIR + deviceName.replace(" ","-"); //take into account spaces in the name
177
178  //Create the fileystem specific command for mounting
179  QString fstype;
180  QString fsopts="";
181  if( filesystem == "FAT" ){ fstype = "mount -t msdosfs"; fsopts = "-o large,-m=644,-M=777"; }
182  else if(filesystem == "NTFS"){ fstype = "ntfs-3g"; }
183  else if(filesystem == "EXT"){ fstype = "mount -t ext2fs"; }
184  else if(filesystem == "CD9660"){ fstype = "mount -t cd9660"; }
185  else if(filesystem == "UFS"){ fstype = "mount -t ufs"; }
186  else if(filesystem == "REISERFS"){ fstype = "mount -t reiserfs"; }
187  else if(filesystem == "XFS"){ fstype = "mount -t xfs"; }
188  else{
189    qDebug() << "Unknown device filesystem:" << device << filesystem << " attempting mount_auto command";
190    fstype = "mount_auto";
191    //QMessageBox::warning(this,tr("Unknown Device Filesystem"),tr("The filesystem on this device is unknown and cannot be mounted at this time") );
192    //return FALSE;
193  }
194  //Make sure the mntpoint is available
195  QDir mpd(mntpoint);
196  if(mpd.exists()){
197    //Remove the existing directory (will work only if it is empty)
198    mpd.cdUp();
199    mpd.rmdir(mntpoint);
200  }
201  //Prepare the commands to run
202  QString cmd1 = "mkdir " + mntpoint;
203  QString cmd2 = fstype + " " +fsopts + " " + device + " " + mntpoint;
204  QString cmd3 = "chmod 777 " + mntpoint; //to set full user/root access
205 
206  qDebug() << "Mounting device" << device << "on" << mntpoint << "("<<filesystem<<")";
207  if(DEBUG_MODE){ qDebug() << " - command:" << cmd2; }
208 
209  bool ok = FALSE;
210  QString result, title;
211  //Run the mounting commands
212  QStringList output = Utils::runShellCommand(cmd1);
213  if( output.join(" ").simplified().isEmpty() ){
214    //directory created, run the next commands
215    system(cmd3.toUtf8()); //set directory permissions before mounting device
216    output = Utils::runShellCommand(cmd2);
217    if( output.join(" ").simplified().isEmpty() ){
218      title = tr("Success");
219      result = QString( tr("%1 mounted at %2") ).arg(deviceName).arg(mntpoint);
220      ok = TRUE;
221    }else{
222      qDebug() << "pc-mounttray: Error mounting device:" << device;
223      qDebug() << " - Error message:" << output;
224      title = QString( tr("Error mounting %1 at %2") ).arg(deviceName).arg(mntpoint);
225      result =  output.join(" ");
226      //Remove the mount point just created
227      Utils::runShellCommand("rmdir "+mntpoint);
228    }
229  }else{
230    qDebug() << "pc-mounttray: Error creating mountpoint:" << mntpoint;
231    qDebug() << " - Error message:" << output;
232    title = QString( tr("Error mounting %1") ).arg(deviceName);
233    result =  QString( tr("Could not create mount point at %1") ).arg(mntpoint);
234  }
235  //Output the proper signals depending upon success
236  if(ok){
237    emit itemMounted(mntpoint);
238    mountpoint = mntpoint;
239  }else{
240    mountpoint.clear();
241  }
242  if( !checkAutomount->isChecked() ){
243    emit newMessage(title, result); //suppress the output message if it was automounted
244  }
245 
246}
247
248void MenuItem::unmountItem(){
249  //Unmount the device
250
251  //Check to see if the current mountpoint exists or if it is somewhere else
252  if( !QFile::exists(mountpoint) ){
253    if( isMounted() ){  //double check that it is actually mounted
254      //mounted someplace else - find it
255      QString output = Utils::runShellCommandSearch("mount",device);
256      mountpoint = output.section(" on ",1,1).section(" (",0,0).replace(" ","-");
257    }else{
258      //it is not mounted to begin with
259      return;
260    }
261  }
262 
263  QString cmd1 = "umount " + mountpoint;
264  QString cmd2 = "rmdir " + mountpoint;
265  qDebug() << "Unmounting device from" << mountpoint;
266  //Run the commands
267  QStringList output;
268  QString result, title;
269  bool ok = FALSE;
270  output = Utils::runShellCommand(cmd1);
271  if(output.join(" ").simplified().isEmpty()){
272    //unmounting successful, remove the mount point directory
273    output = Utils::runShellCommand(cmd2);
274    if(!output.join(" ").simplified().isEmpty()){
275      qDebug() << "pc-mounttray: Error removing mountpoint:" << mountpoint;
276      qDebug() << " - Error message:" << output;
277    }
278    ok = TRUE;
279    title = QString( tr("%1 has been successfully unmounted.") ).arg(devLabel->text());
280    result = tr("It is now safe to remove the device");
281  }else{
282    qDebug() << "pc-mounttray: Error unmounting mountpoint:" << mountpoint;
283    qDebug() << " - Error message:" << output;
284    title = QString( tr("Error: %1 could not be unmounted") ).arg(devLabel->text());
285    result = output.join(" ");
286  }
287  //emit the proper signals
288  if(ok){
289    emit itemUnmounted(device);
290    mountpoint.clear();
291  }
292  emit newMessage(title, result);
293}
294
295void MenuItem::updateSizes(){
296  //this method only works if the device is currently mounted
297  bool ok = FALSE;
298  if(isMounted()){
299    QString cmd = "df "+mountpoint;
300    QStringList output = systemCMD(cmd); //make sure we use the one with a 1K blocksize
301    if(output.length() > 1){
302      //parse the output (1K blocks) and save them
303      QString line = output[1].replace("\t"," ");
304      //qDebug() << "df output:" << output << cmd;
305      maxSize = line.section(" ",1,1,QString::SectionSkipEmpty).simplified();
306      currentSize = line.section(" ",2,2,QString::SectionSkipEmpty).simplified();
307      ok=TRUE;
308    }else{
309      maxSize.clear();
310      currentSize.clear();         
311    }
312  }else{
313    maxSize.clear();
314    currentSize.clear();
315  }
316  //Now setup the display progressbar display
317  if(ok){
318    currentSpace->setMaximum( maxSize.toInt() );
319    currentSpace->setValue( currentSize.toInt() );
320    currentSpace->setVisible(TRUE);
321    //display the actual size available in the tooltip
322    QString diskAvailable = getSizeDisplay( maxSize.toInt() - currentSize.toInt() );
323    //qDebug() << "MaxSize:" << maxSize << maxSize.toInt();
324    //qDebug() << "CurrentSize:" << currentSize << currentSize.toInt();
325    //qDebug() << "Disk Available:" << diskAvailable;
326    currentSpace->setToolTip( QString( tr("%1 of disk space available") ).arg(diskAvailable) );
327  }else{
328    currentSpace->setVisible(FALSE);
329  }
330       
331}
332
333QString MenuItem::getSizeDisplay(int kb){
334  //convert from KB to human readable output
335  if( kb > 1048576 ){ //display in GB
336    return QString::number( double(int( (kb*100)/1048576 )/100.0) )+"GB";
337  }else if( kb > 1024 ){ //display in MB
338    return QString::number( double(int( (kb*100)/1024 )/100.0) )+"MB";   
339  }else{ //display in KB
340    return QString::number( kb )+"KB";   
341  }
342       
343}
344
345QStringList MenuItem::systemCMD(QString command){ 
346   QProcess p;
347   QString outstr;
348   //Make sure we use the system environment to properly read system variables, etc.
349   QProcessEnvironment penv = QProcessEnvironment::systemEnvironment();
350   penv.insert("BLOCKSIZE","K"); //make sure we use a 1KB block size
351   p.setProcessEnvironment(penv);
352   //Merge the output channels to retrieve all output possible
353   p.setProcessChannelMode(QProcess::MergedChannels);   
354   p.start(command);
355   while(p.state()==QProcess::Starting || p.state() == QProcess::Running){
356     p.waitForFinished(200);
357     QCoreApplication::processEvents();
358   }
359   QString tmp = p.readAllStandardOutput();
360   outstr.append(tmp);
361   if(outstr.endsWith("\n")){outstr.chop(1);} //remove the newline at the end
362   QStringList out = outstr.split("\n");
363   return out;
364}
Note: See TracBrowser for help on using the repository browser.