I want to save the screenshot of my application to the desktop. The problem is, it saves but if I take another screenshot it replaces the old image. How can I tell Qt to call it Wishlist 1, Wishlist 2 etc.?
QString filepath = QDir::toNativeSeparators( QDir::homePath() + "/Desktop/Wishlist.png" );
if( grab().save( filepath, "png" ) )
statusBar()->showMessage( tr("Saved file to Desktop.") );
else
statusBar()->showMessage( tr("Error saving file.") );
After I close and start the program again, it should be able to go on. E.g. Wishlist 1, Wishlist 2 then restart and then it should name the next screenshot Wishlist 3.
create a function for resolving the filename. the following snippet is not safe (what if no get's too large) and for the no == 0 you need a special case.
int no = 0;
while( true ){
QString path = filename + "." + QString::number( no ) + "." + extention;
QFileInfo fileInfo( path );
if( !fileInfo.exists() )
return path;
no++
}
Related
I can't get the Perl script below to write to the file output.html.
I doesn't need to be a CGI script yet, but that is the ultimate intention.
Can anyone tell me why it isn't writing any text to output.html?
#!/usr/bin/perl
#-----------------------------------------------------------------------
# This script should work as a CGI script, if I get it correctly.
# Most CGI scripts for Perl begin with the same line and must be
# stored in your servers cgi-bin directory. (I think this is set by
# your web server.
#
# This scripts will scrape news sites for stories about topics input
# by the users.
#
# Lara Landis
# Sinister Porpoise Computing
# 1/4/2018
# Personal Perl Project
#-----------------------------------------------------------------------
#global_sites = ();
print( "Starting program.\n" );
if ( !( -e "sitedata.txt" ) ) {
enter_site_info( #global_sites );
}
if ( !( -e "scrpdata.txt" ) ) {
print( "scrpdata.txt does not exist. Creating file now.\n" );
print( "Enter the search words you wish to search for below. Press Ctrl-D to finish.\n" );
open( SCRAPEFILE, ">scrpdata.txt" );
while ( $line = <STDIN> ) {
chop( $line );
print SCRAPEFILE ( "$line\n" );
}
close( SCRAPEFILE );
}
print( "Finished getting site data..." );
scrape_sites( #global_sites );
#----------------------------------------------------------------------
# This routine gets information from the user after the file has been
# created. It also has some basic checking to make sure that the lines
# fed to it are legimate domains. This is not an exhaustive list of
# all domains in existence.
#----------------------------------------------------------------------
sub enter_site_info {
my ( #sisites ) = #_;
$x = 1;
open( DATAFILE, ">sitedata.txt" ) || die( "Could not open datafile.\n" );
print( "Enter websites below. Press Crtl-D to finish.\n" );
while ( $x <= #sisites ) {
$sisites[$x] = <STDIN>;
print( "$sisites[$x] added.\n" );
print DATAFILE ( "$sisites[$x]\n" );
$x++;
}
close( DATAFILE );
return #sisites;
}
#----------------------------------------------------------------------
# If the file exists, just get the information from it. Read info in
# from the sites. Remember to create a global array for the sites
# data.
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
# Get the text to find in the sites that are being scraped. This requires
# nested loops. It starts by going through the loops for the text to be
# scraped, and then it goes through each of the websites listend in the
# sitedata.txt file.
#-----------------------------------------------------------------------
sub scrape_sites {
my ( #ss_info ) = #_;
#gsi_info = ();
#toscrape = ();
$y = 1;
#---------------------------
# Working code to be altered
#---------------------------
print( "Getting site info..." );
$x = 1;
open( DATAFILE, "sitedata.txt" ) || die( "Can't open sitedata.txt.txt\n" );
while ( $gsi_info[$x] = <DATAFILE> ) {
chop( $gsi_info[$x] );
print( "$gsi_info[$x]\n" );
$x++;
}
close( DATAFILE );
open( SCRAPEFILE, "scrpdata.txt" ) || die( "Can't open scrpdata.txt\n" );
print( "Getting scrape data.\n" );
$y = 1;
while ( $toscrape[$y] = <SCRAPEFILE> ) {
chop( $toscrape[$y] );
$y++;
}
close( SCRAPEFILE );
print( "Now opening the output file.\n" );
$z = 1;
open( OUTPUT, ">output.html" );
print( "Now scraping sites.\n" );
while ( $z <= #gsi_info ) { #This loop contains SITES
system( "rm -f index.html.*" );
system( "wget $gsi_info[$z]" );
$z1 = 1;
print( "Searching site $gsi_info[$z] for $toscrape[$z1]\n" );
open( TEMPFILE, "$gsi_info[$z]" );
$comptext = <TEMPFILE>;
while ( $comptext =~ /$toscrape[z1]/ig ) { # This loop fetches data from the search terms
print( "Now scraping $gsi_info[$z] for $toscrape[$z1]\n" );
print OUTPUT ( "$toscrape[$z1]\n" );
$z1++;
}
close( TEMPFILE );
$z++;
}
close( OUTPUT );
return ( #gsi_info );
}
You're making assumptions about the current work directory that are often incorrect. You seem to assume the current work directory is the directory in which the script resides, but that's never guaranteed, and it's often / for CGI scripts.
"sitedata.txt"
should be
use FindBin qw( $RealBin );
"$RealBin/sitedata.txt"
There could also be a permission error. You should include the error cause ($!) in your error message when open fails so you know what is causing the problem!
While you're checking some, you're not checking all of your open or system calls. If they fail, the program will keep going without an error message telling you why.
You can add checks to all of these, but it's easy to forget. Instead, use autodie to do the checks for you.
You'll also want to use strict to ensure you haven't made any variable typos, and use warnings to warn you about small mistakes. See this answer for more.
Also #global_sites is empty so enter_site_info() isn't going to do anything. And scrape_sites() does nothing with its argument, #ss_info.
All of these things are helpful. Thank you. I found the problem. I was opening the wrong file. It was putting the error-checking in on the file that let me spot the error. It should have been
open (TEMPFILE, "index.html") || die ("Cannot open index.html\n");
I have taken as many of the suggestions as I remembered and included them in the code. I still need to implement the directory advice, but it should not be difficult.
I have the following query and the last part of it is to check the state of the item which will be 1 or 0;
My api calls:
http://example.com/api/search?keyword=someword&search_for=item&return_product
The query works as expected, except for one thing. Some of the stone items are disabled and I need to ignore where:
->where('S.state=:state')
->setParameter('state' , 1 )
I am not quite sure where to add this to the current query to get it to work:
$qb = $this->stoneRepository->createQueryBuilder('S');
//Get the image for the item
$qb->addSelect('I')
->leftJoin('S.image' , 'I');
//Check if we want products returned
if ( $return_product )
{
$qb->addSelect('P','PI')
->leftJoin('S.product' , 'P')
->leftJoin('P.image' , 'PI');
}
//Check is we want attributes returned
if ( $return_attribute )
{
$qb->addSelect('A','C')
->leftJoin('S.attribute' , 'A')
->leftJoin('A.category' , 'C');
}
//Check the fields for matches
$qb->add('where' , $qb->expr()->orX(
$qb->expr()->like('S.name' , ':keyword'),
$qb->expr()->like('S.description' , ':keyword')
)
);
//Set the search item
$qb->setParameter('keyword', '%'.$keyword.'%');
$qb->add('orderBy', 'S.name ASC');
Just after the createQueryBuilder call:
$qb = $this->stoneRepository
->createQueryBuilder('S')
->where('S.state = :state')
->setParameter('state', 1);
With the query builder the order is not important: you can add SQL pieces in different order and even override pieces already added.
I've a text file with its backup copy: backup copy has the same name with only a "2" as last character of the extension (example: Original: Myfile.txt - Backup: Myfile.txt2).
Sometimes I need to replace the original one with the backup; I do the following:
QFile BackupFile("Myfile.txt2"); // backup copy
QString nameFile = BackupFile.fileName();// name of backup copy of file
nameFile.chop(1); // remove the last letter of file name, so nameFile now is the same of Original file
QFile originalFile(nameFile); // Original copy
originalFile.remove(); // delete the original file
BackupFile.rename(nameFile); // rename the backup file as original
BackupFile.close(); // close the file
This works, but it seems too complex. I'd like something easier.
Do you have any suggestion?
I think this code can be simple method. However, you should add code for error case, such as 'check whether backup file exist.', etc..
auto ReplaceWithBackup = []( QString& backupName ) -> bool
{
QString originName = backupName;
originName.chop( 1 );
if ( QFile::exists( originName ) )
{
QFile::remove( originName );
}
return QFile::rename( backupName, originName );
};
if ( ReplaceWithBackup( "Myfile.txt2") == false )
{
// error
}
If the files are in the same directory, you can use QDir::rename. Otherwise reading one file and writing in the other is required. Here is my version of the first case.
// Generate some test data
{
QFile bf( "Myfile.txt2" );
bf.open(QIODevice::WriteOnly);
bf.write("Backup data");
QFile( "Myfile.txt" ).open(QIODevice::WriteOnly);
}
//Assume you know which back-up file to restore
QString backupFn("Myfile.txt2");
//Actual code
QString origFn = backupFn.mid( 0, backupFn.size()-1 ); //"guess" the original file name.
QFile::remove( origFn ); //Use static version to delete file by name (No QFile instance required)
QDir().rename(backupFn,origFn);
However, each line requires many checks and validations e.g. is the provided backup-file name a valid backup name, did remove/rename succeded, etc, etc.
I have a piece of code to download a file from server. However, due to server constraint, I can not put .exe file at server. So I rename my XXX.exe file to XXX.alt(just a random extension) and put it on server.
Now my code can download XXX.alt, but how can I change the file name from XXX.alt back to XXX.exe when in QT environment?
Use QFileInfo to get the path without the last extension then append the new extension.
QFileInfo info(fileName);
QString strNewName = info.path() + "/" + info.completeBaseName() + ".exe";
Just use rename function from 'stdio.h'.
char oldname[] ="XXX.alt";
char newname[] ="XXX.exe";
result= rename( oldname , newname );
if ( result == 0 )
puts ( "File successfully renamed" );
else
perror( "Error renaming file" );
One solution is to find the last '.', and replace the substring from that position to the end with the substring you want.
Exactly how to do it, there are many ways using both std::string and QString, as both support finding characters in the string (and doing a search from the end to the beginning as well), and replace substrings.
Prefer to use baseName()
QFileInfo info(fileName);
QString strNewName = info.path() + info.baseName() + ".exe";
QString QFileInfo::completeBaseName () const
Returns file name with shortest extension removed (file.tar.gz -> file.tar)
QString QFileInfo::baseName () const
Returns file name with longest extension removed (file.tar.gz -> file)
I wanted to validate a file name along with its full path. I tried certain Regular Expressions as below but none of them worked correctly.
^(?:[\w]\:|\\)(\\[a-z_\-\s0-9\.]+)+\.(txt|gif|pdf|doc|docx|xls|xlsx)$
and
^(([a-zA-Z]\:)|(\\))(\\{1}|((\\{1})[^\\]([^/:*?<>""|]*))+)$
etc...
My requirement is as mentioned below:
Lets say if the file name is "c:\Demo.txt" then it should check every possibilites like no double slash should be included(c:\\Demo\\demo.text) no extra colon like(c::\Demo\demo.text). Should accept UNC files like(\\staging\servers) and others validation as well. Please help. I am really stuck here.
Why are you not using the File class ?
Always use it !
File f = null;
string sPathToTest = "C:\Test.txt";
try{
f = new File(sPathToTest );
}catch(Exception e){
Console.WriteLine(string.Format("The file \"{0}\" is not a valid path, Error : {1}.", sPathToTest , e.Message);
}
MSDN : http://msdn.microsoft.com/en-gb/library/system.io.file%28v=vs.80%29.aspx
Maybe you're just looking for File.Exists ( http://msdn.microsoft.com/en-gb/library/system.io.file.exists%28v=vs.80%29.aspx )
Also take a look to the Path class ( http://msdn.microsoft.com/en-us/library/system.io.path.aspx )
The GetAbsolutePath could be one way to get what you want! ( http://msdn.microsoft.com/en-us/library/system.io.path.getfullpath.aspx )
string sPathToTest = "C:\Test.txt";
string sAbsolutePath = "";
try{
sAbsolutePath = Path.GetAbsolutePath(sPathToTest);
if(!string.IsNullOrEmpty(sAbsolutePath)){
Console.WriteLine("Path valid");
}else{
Console.WriteLine("Bad path");
}
}catch(Exception e){
Console.WriteLine(string.Format("The file \"{0}\" is not a valid path, Error : {1}.", sPathToTest , e.Message);
}
If you are interested only in the filename part (and not the whole path because you get the file via upload) then you could try something like this:
string uploadedName = #"XX:\dem<<-***\demo.txt";
int pos = uploadedName.LastIndexOf("\\");
if(pos > -1)
uploadedName = uploadedName.Substring(pos+1);
var c = Path.GetInvalidFileNameChars();
if(uploadedName.IndexOfAny(c) != -1)
Console.WriteLine("Invalid name");
else
Console.WriteLine("Acceptable name");
This will avoid the use of Exceptions as method to drive the logic of your code.